flutterby 0.4.0 → 0.5.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.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/.yardopts +2 -0
- data/CHANGES.md +13 -0
- data/README.md +3 -2
- data/bin/yard +17 -0
- data/bin/yardoc +17 -0
- data/bin/yri +17 -0
- data/flutterby.gemspec +1 -0
- data/lib/flutterby.rb +2 -0
- data/lib/flutterby/cli.rb +12 -6
- data/lib/flutterby/dotaccess.rb +31 -0
- data/lib/flutterby/exporter.rb +15 -13
- data/lib/flutterby/filters.rb +15 -15
- data/lib/flutterby/node.rb +205 -150
- data/lib/flutterby/node_extension.rb +23 -0
- data/lib/flutterby/server.rb +9 -8
- data/lib/flutterby/tree_walker.rb +37 -0
- data/lib/flutterby/version.rb +1 -1
- data/lib/flutterby/view.rb +51 -8
- data/lib/templates/new_project/site/_config.yaml +9 -0
- data/lib/templates/new_project/site/_layout.slim +3 -2
- data/lib/templates/new_project/site/blog/_init.rb +11 -0
- data/lib/templates/new_project/site/blog/_layout.slim +1 -1
- data/lib/templates/new_project/site/blog/hello-world.html.md.tt +1 -1
- data/lib/templates/new_project/site/index.html.slim +1 -1
- metadata +25 -4
- data/lib/templates/new_project/site/_config.toml +0 -10
- data/lib/templates/new_project/site/blog/_node.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 679b8fba9c9fda2c5e70df5bb73a16903be5181f
|
4
|
+
data.tar.gz: 5a27688b1713d0bd8bb49695afcb1bb9272682e6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b24fcfd4c696520de83fcc2f6a0318f7e3895bf558bdc30145ccf8eca1af57845fca6c393ceac928edcfa3afaf5f99409324d9027269c88a89fd698d6512c35c
|
7
|
+
data.tar.gz: 8a2827f70bc5484a202d9f147e7c0cb0ba04ee3e95106041ceb8439e014321b01474a9273e3d2bcbbcba740eed03263c4d5b86bdb848a453cf13602647da2edb
|
data/.travis.yml
CHANGED
data/.yardopts
ADDED
data/CHANGES.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Version History
|
2
2
|
|
3
|
+
### 0.5.0 (2017-01-24)
|
4
|
+
|
5
|
+
- **NEW:** Nodes have two new attributes, `prefix` and `slug`, which are automatically generated from the node's name. If the name starts with a combination of decimals and dashes, these will become the `prefix`, and the remainder auf the name the `suffix`. For example, a name of `123-introduction` will result in a prefix of `123` and a slug of `introduction`. As before, a prefix that looks like a date (eg. `2017-04-01-introduction`) will automatically be parsed into `data[:date]`.
|
6
|
+
- **NEW:** When nodes are being spawned, their names will be changed to their slugs by default (ie. any prefix contained in the original name will be removed.) For example, a `123-foo.html.md` will be exported as just `foo.html`.
|
7
|
+
- **NEW:** Nodes now have first-class support of a node title through the new `title` attribute. This will either use `data[:title]`, when available, or generate a title from `slug` (eg. a node named `hello-world.html.md` will automatically have a title of `Hello World`.)
|
8
|
+
- **NEW:** You can now also access a node's data using a convenient dot syntax; eg. `node.data.foo.bar` will return `node.data[:foo][:bar]`. If you're on Ruby 2.3 or newer, this allows you to use the safe navigation operator; eg. `data.foo&.bar`.
|
9
|
+
- **BREAKING CHANGE:** The `_node.rb` mechanism is gone. In its stead, you can now add `_init.rb` files that will be evaluated automatically; those can use the new `extend_siblings` and `extend_parent` convenience methods to extend all available siblings (or the parent) with the specified module or block.
|
10
|
+
- **NEW:** These node extensions can now supply an `on_setup` block that will be executed after the tree has been fully spawned. You can use these setup blocks to further modify the tree.
|
11
|
+
- **NEW:** The `flutterby build` and `flutterby serve` CLI commands now provide additional debug output when started with the `--debug` option.
|
12
|
+
- **NEW:** Added `Node#create` as a convenience method for creating new child nodes below a given node.
|
13
|
+
- **CHANGE:** Some massive refactoring, the primary intent being to perform the rendering of nodes in a thread-safe manner.
|
14
|
+
|
15
|
+
|
3
16
|
### 0.4.0 (2017-01-21)
|
4
17
|
|
5
18
|
- **NEW:** Flutterby views now have a `tag` helper method available that can generate HTML tags programatically.
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Flutterby
|
1
|
+
# Flutterby 🦋
|
2
2
|
|
3
3
|
### A flexible, Ruby-powered static site generator.
|
4
4
|
|
@@ -17,8 +17,9 @@
|
|
17
17
|
|
18
18
|
- [Blog post introducing Flutterby](http://hmans.io/posts/2017/01/11/flutterby.html)
|
19
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)
|
20
21
|
- [Version History](https://github.com/hmans/flutterby/blob/master/CHANGES.md)
|
21
|
-
- [Roadmap](https://github.com/hmans/flutterby/
|
22
|
+
- [Issues/Roadmap](https://github.com/hmans/flutterby/issues)
|
22
23
|
- [Sites built with Flutterby](https://github.com/hmans/flutterby/wiki/Sites-built-with-Flutterby) (add yours!)
|
23
24
|
|
24
25
|
|
data/bin/yard
ADDED
@@ -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 'yard' 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("yard", "yard")
|
data/bin/yardoc
ADDED
@@ -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 'yardoc' 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("yard", "yardoc")
|
data/bin/yri
ADDED
@@ -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 'yri' 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("yard", "yri")
|
data/flutterby.gemspec
CHANGED
@@ -30,6 +30,7 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.add_development_dependency 'awesome_print', '~> 0'
|
31
31
|
spec.add_development_dependency 'gem-release', '~> 0'
|
32
32
|
spec.add_development_dependency 'pry', '~> 0.10'
|
33
|
+
spec.add_development_dependency 'yard', '~> 0.9'
|
33
34
|
|
34
35
|
spec.add_dependency 'erubis', '~> 2.7'
|
35
36
|
spec.add_dependency 'erubis-auto', '~> 1.0'
|
data/lib/flutterby.rb
CHANGED
data/lib/flutterby/cli.rb
CHANGED
@@ -21,10 +21,13 @@ module Flutterby
|
|
21
21
|
end
|
22
22
|
|
23
23
|
desc "build", "Build your static site"
|
24
|
-
option :in, default: "./site/", aliases: [
|
25
|
-
option :out, default: "./_build/", aliases: [
|
24
|
+
option :in, default: "./site/", aliases: ["-i"]
|
25
|
+
option :out, default: "./_build/", aliases: ["-o"]
|
26
|
+
option :debug, default: false, aliases: ["-d"], type: :boolean
|
26
27
|
|
27
28
|
def build
|
29
|
+
Flutterby.logger.level = options.debug ? Logger::DEBUG : Logger::INFO
|
30
|
+
|
28
31
|
# Simplify logger output
|
29
32
|
Flutterby.logger.formatter = proc do |severity, datetime, progname, msg|
|
30
33
|
" • #{msg}\n"
|
@@ -49,10 +52,13 @@ module Flutterby
|
|
49
52
|
|
50
53
|
|
51
54
|
desc "serve", "Serve your site locally"
|
52
|
-
option :in, default: "./site/", aliases: [
|
53
|
-
option :port, default: 4004, aliases: [
|
55
|
+
option :in, default: "./site/", aliases: ["-i"]
|
56
|
+
option :port, default: 4004, aliases: ["-p"], type: :numeric
|
57
|
+
option :debug, default: false, aliases: ["-d"], type: :boolean
|
54
58
|
|
55
59
|
def serve
|
60
|
+
Flutterby.logger.level = options.debug ? Logger::DEBUG : Logger::INFO
|
61
|
+
|
56
62
|
say_hi
|
57
63
|
|
58
64
|
say color("📚 Importing site...", :bold)
|
@@ -61,8 +67,8 @@ module Flutterby
|
|
61
67
|
say color("🌲 Read #{root.tree_size} nodes.", :green, :bold)
|
62
68
|
|
63
69
|
say color("🌤 Serving your Flutterby site on http://localhost:#{options.port} - enjoy! \\o/", :bold)
|
64
|
-
server = Flutterby::Server.new(root
|
65
|
-
server.run!
|
70
|
+
server = Flutterby::Server.new(root)
|
71
|
+
server.run!(port: options.port)
|
66
72
|
end
|
67
73
|
|
68
74
|
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Dotaccess
|
2
|
+
class Proxy
|
3
|
+
def initialize(hash)
|
4
|
+
@hash = hash
|
5
|
+
end
|
6
|
+
|
7
|
+
def method_missing(meth, *args)
|
8
|
+
if @hash.respond_to?(meth)
|
9
|
+
@hash.send(meth, *args)
|
10
|
+
elsif meth =~ %r{\A(.+)=\Z}
|
11
|
+
@hash[$1] = args.first
|
12
|
+
elsif v = (@hash[meth] || @hash[meth.to_s])
|
13
|
+
v.is_a?(Hash) ? Proxy.new(v) : v
|
14
|
+
else
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def [](k)
|
20
|
+
@hash[k]
|
21
|
+
end
|
22
|
+
|
23
|
+
def ==(o)
|
24
|
+
@hash == o
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.[](hash)
|
29
|
+
Proxy.new(hash)
|
30
|
+
end
|
31
|
+
end
|
data/lib/flutterby/exporter.rb
CHANGED
@@ -5,25 +5,27 @@ module Flutterby
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def export!(into:)
|
8
|
-
@root
|
9
|
-
|
10
|
-
|
8
|
+
export_node(@root, into: into)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def export_node(node, into:)
|
14
|
+
return unless node.should_publish?
|
11
15
|
|
12
|
-
|
13
|
-
# Make sure directory exists
|
14
|
-
FileUtils.mkdir_p(::File.dirname(path))
|
16
|
+
path = ::File.expand_path(::File.join(into, node.full_name))
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
if node.file?
|
19
|
+
::File.write(path, node.render(layout: true))
|
20
|
+
logger.info "Exported #{node.url}"
|
21
|
+
else
|
22
|
+
FileUtils.mkdir_p(path)
|
23
|
+
node.children.each do |child|
|
24
|
+
export_node(child, into: path)
|
20
25
|
end
|
21
26
|
end
|
22
27
|
end
|
23
28
|
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
29
|
def logger
|
28
30
|
@logger ||= Flutterby.logger
|
29
31
|
end
|
data/lib/flutterby/filters.rb
CHANGED
@@ -8,19 +8,19 @@ require 'flutterby/markdown_formatter'
|
|
8
8
|
|
9
9
|
module Flutterby
|
10
10
|
module Filters
|
11
|
-
def self.apply!(
|
12
|
-
|
11
|
+
def self.apply!(view)
|
12
|
+
view._body = view.source.try(:html_safe)
|
13
13
|
|
14
14
|
# Apply all filters
|
15
|
-
node.filters.each do |filter|
|
15
|
+
view.node.filters.each do |filter|
|
16
16
|
meth = "process_#{filter}!"
|
17
17
|
|
18
18
|
if Filters.respond_to?(meth)
|
19
|
-
Filters.send(meth,
|
20
|
-
elsif template = tilt(filter,
|
21
|
-
|
19
|
+
Filters.send(meth, view)
|
20
|
+
elsif template = tilt(filter, view._body)
|
21
|
+
view._body = template.render(view).html_safe
|
22
22
|
else
|
23
|
-
Flutterby.logger.warn "Unsupported filter '#{filter}' for #{node.url}"
|
23
|
+
Flutterby.logger.warn "Unsupported filter '#{filter}' for #{view.node.url}"
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
@@ -43,23 +43,23 @@ module Flutterby
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
Flutterby::Filters.add("rb") do |
|
47
|
-
|
46
|
+
Flutterby::Filters.add("rb") do |view|
|
47
|
+
view._body = view.instance_eval(view._body)
|
48
48
|
end
|
49
49
|
|
50
|
-
Flutterby::Filters.add(["md", "markdown"]) do |
|
51
|
-
|
50
|
+
Flutterby::Filters.add(["md", "markdown"]) do |view|
|
51
|
+
view._body = Flutterby::MarkdownFormatter.new(view._body).complete.to_s.html_safe
|
52
52
|
end
|
53
53
|
|
54
|
-
Flutterby::Filters.add("scss") do |
|
54
|
+
Flutterby::Filters.add("scss") do |view|
|
55
55
|
sass_options = {
|
56
56
|
syntax: :scss,
|
57
57
|
load_paths: []
|
58
58
|
}
|
59
59
|
|
60
|
-
if node.fs_path
|
61
|
-
sass_options[:load_paths] << File.dirname(node.fs_path)
|
60
|
+
if view.node.fs_path
|
61
|
+
sass_options[:load_paths] << File.dirname(view.node.fs_path)
|
62
62
|
end
|
63
63
|
|
64
|
-
|
64
|
+
view._body = Sass::Engine.new(view._body, sass_options).render
|
65
65
|
end
|
data/lib/flutterby/node.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
-
require '
|
1
|
+
require 'flutterby/node_extension'
|
2
2
|
|
3
3
|
module Flutterby
|
4
4
|
class Node
|
5
5
|
attr_accessor :name, :ext, :source
|
6
|
-
|
7
|
-
attr_reader :
|
6
|
+
attr_reader :filters, :parent, :fs_path, :children
|
7
|
+
attr_reader :prefix, :slug
|
8
|
+
attr_reader :_setup_procs
|
8
9
|
|
9
10
|
def initialize(name, parent: nil, fs_path: nil, source: nil)
|
10
11
|
@fs_path = fs_path ? ::File.expand_path(fs_path) : nil
|
11
12
|
@source = source
|
13
|
+
@_setup_procs = []
|
12
14
|
|
13
15
|
# Extract name, extension, and filters from given name
|
14
16
|
parts = name.split(".")
|
@@ -24,21 +26,66 @@ module Flutterby
|
|
24
26
|
reload!
|
25
27
|
end
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
module Paths
|
30
|
+
# Returns the node's URL.
|
31
|
+
#
|
32
|
+
def url
|
33
|
+
::File.join(parent ? parent.url : "/", full_name)
|
32
34
|
end
|
35
|
+
end
|
33
36
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
37
|
+
include Paths
|
38
|
+
|
39
|
+
|
40
|
+
module Tree
|
41
|
+
# Returns the tree's root node.
|
42
|
+
#
|
43
|
+
def root
|
44
|
+
parent ? parent.root : self
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns true if this node is also the tree's root node.
|
48
|
+
#
|
49
|
+
def root?
|
50
|
+
root == self
|
51
|
+
end
|
52
|
+
|
53
|
+
def sibling(name)
|
54
|
+
parent && parent.find(name)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns this node's siblings (ie. other nodes within the
|
58
|
+
# same folder node.)
|
59
|
+
#
|
60
|
+
def siblings
|
61
|
+
parent && (parent.children - [self])
|
62
|
+
end
|
63
|
+
|
64
|
+
# Among this node's children, find a node by its name. If the
|
65
|
+
# name passed as an argument includes a dot, the name will match against
|
66
|
+
# the full name of the children; otherwise, just the base name.
|
67
|
+
#
|
68
|
+
# Examples:
|
69
|
+
#
|
70
|
+
# # returns the first child called "index"
|
71
|
+
# find_child("index")
|
72
|
+
#
|
73
|
+
# # returns the child called "index" with extension "html"
|
74
|
+
# find_child("index.html")
|
75
|
+
#
|
76
|
+
def find_child(name, opts = {})
|
77
|
+
name_attr = name.include?(".") ? "full_name" : "name"
|
78
|
+
|
79
|
+
@children.find do |c|
|
80
|
+
(c.should_publish? || !opts[:public_only]) &&
|
81
|
+
(c.send(name_attr) == name)
|
39
82
|
end
|
40
83
|
end
|
41
84
|
|
85
|
+
def emit_child(name)
|
86
|
+
# Override this to dynamically create child nodes.
|
87
|
+
end
|
88
|
+
|
42
89
|
def tree_size
|
43
90
|
children.inject(children.length) do |count, child|
|
44
91
|
count + child.tree_size
|
@@ -46,109 +93,89 @@ module Flutterby
|
|
46
93
|
end
|
47
94
|
|
48
95
|
def parent=(new_parent)
|
96
|
+
# Remove from previous parent
|
49
97
|
if @parent
|
50
98
|
@parent.children.delete(self)
|
51
99
|
end
|
52
100
|
|
101
|
+
# Assign new parent (it may be nil)
|
53
102
|
@parent = new_parent
|
54
103
|
|
55
|
-
|
104
|
+
# Notify new parent
|
105
|
+
if @parent
|
106
|
+
@parent.children << self
|
107
|
+
end
|
56
108
|
end
|
57
109
|
|
58
110
|
# Returns all children that will compile to a HTML page.
|
59
111
|
#
|
60
112
|
def pages
|
61
|
-
children.select { |c| c.
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
concerning :Paths do
|
66
|
-
def path
|
67
|
-
parent ? ::File.join(parent.path, full_name) : full_name
|
68
|
-
end
|
69
|
-
|
70
|
-
def url
|
71
|
-
::File.join(parent ? parent.url : "/", full_name)
|
72
|
-
end
|
73
|
-
|
74
|
-
def full_fs_path(base:)
|
75
|
-
::File.expand_path(::File.join(base, full_name))
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
|
80
|
-
concerning :Tree do
|
81
|
-
def root
|
82
|
-
parent ? parent.root : self
|
83
|
-
end
|
84
|
-
|
85
|
-
def root?
|
86
|
-
root == self
|
87
|
-
end
|
88
|
-
|
89
|
-
def sibling(name)
|
90
|
-
parent && parent.find(name)
|
113
|
+
children.select { |c| c.page? }
|
91
114
|
end
|
92
115
|
|
93
|
-
|
94
|
-
|
116
|
+
# Creates a new node, using the specified arguments, as a child
|
117
|
+
# of this node.
|
118
|
+
#
|
119
|
+
def create(name, **args)
|
120
|
+
args[:parent] = self
|
121
|
+
Node.new(name.to_s, **args)
|
95
122
|
end
|
96
123
|
|
97
|
-
def find(path)
|
98
|
-
|
124
|
+
def find(path, opts = {})
|
125
|
+
path = path.to_s
|
126
|
+
return self if path.empty?
|
99
127
|
|
100
128
|
# remove duplicate slashes
|
101
|
-
path.gsub
|
129
|
+
path = path.gsub(%r{/+}, "/")
|
102
130
|
|
103
131
|
case path
|
132
|
+
# ./foo/...
|
104
133
|
when %r{^\./?} then
|
105
|
-
parent ? parent.find($') : root.find($')
|
134
|
+
parent ? parent.find($', opts) : root.find($', opts)
|
135
|
+
|
136
|
+
# /foo/...
|
106
137
|
when %r{^/} then
|
107
|
-
root.find($')
|
138
|
+
root.find($', opts)
|
139
|
+
|
140
|
+
# foo/...
|
108
141
|
when %r{^([^/]+)/?} then
|
109
|
-
child
|
110
|
-
|
142
|
+
# Use the next path part to find a child by that name.
|
143
|
+
# If no child can't be found, try to emit a child, but
|
144
|
+
# not if the requested name starts with an underscore.
|
145
|
+
if child = find_child($1, opts) || (emit_child($1) unless $1.start_with?("_"))
|
146
|
+
# Depending on the tail of the requested find expression,
|
147
|
+
# either return the found node, or ask it to find the tail.
|
148
|
+
$'.empty? ? child : child.find($', opts)
|
149
|
+
end
|
111
150
|
end
|
112
151
|
end
|
152
|
+
end
|
113
153
|
|
114
|
-
|
115
|
-
# found on the way, passing the node as its only argument.
|
116
|
-
#
|
117
|
-
def walk_up(val = nil, &blk)
|
118
|
-
val = blk.call(self, val)
|
119
|
-
parent ? parent.walk_up(val, &blk) : val
|
120
|
-
end
|
154
|
+
include Tree
|
121
155
|
|
122
|
-
# Walk the graph from the root to this node. Just like walk_up,
|
123
|
-
# except the block will be called on higher level nodes first.
|
124
|
-
#
|
125
|
-
def walk_down(val = nil, &blk)
|
126
|
-
val = parent ? parent.walk_up(val, &blk) : val
|
127
|
-
blk.call(self, val)
|
128
|
-
end
|
129
156
|
|
130
|
-
|
157
|
+
module Reading
|
158
|
+
# (Re-)loads the node from the filesystem, if it's a filesystem based
|
159
|
+
# node.
|
131
160
|
#
|
132
|
-
def walk_tree(val = nil, &blk)
|
133
|
-
val = blk.call(self, val)
|
134
|
-
children.each do |child|
|
135
|
-
val = child.walk_tree(val, &blk)
|
136
|
-
end
|
137
|
-
|
138
|
-
val
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
concerning :Reading do
|
143
161
|
def reload!
|
144
|
-
@body = nil
|
145
162
|
@data = nil
|
163
|
+
@data_proxy = nil
|
164
|
+
@prefix = nil
|
165
|
+
@slug = nil
|
146
166
|
@children = []
|
147
|
-
@paths = {}
|
148
167
|
|
149
168
|
load_from_filesystem! if @fs_path
|
169
|
+
|
170
|
+
extract_data!
|
171
|
+
end
|
172
|
+
|
173
|
+
def data
|
174
|
+
@data_proxy ||= Dotaccess[@data]
|
150
175
|
end
|
151
176
|
|
177
|
+
private
|
178
|
+
|
152
179
|
def load_from_filesystem!
|
153
180
|
if @fs_path
|
154
181
|
if ::File.directory?(fs_path)
|
@@ -161,32 +188,41 @@ module Flutterby
|
|
161
188
|
end
|
162
189
|
end
|
163
190
|
end
|
164
|
-
end
|
165
191
|
|
166
|
-
|
167
|
-
def data
|
168
|
-
extract_data! if @data.nil?
|
169
|
-
@data
|
170
|
-
end
|
192
|
+
private
|
171
193
|
|
172
194
|
def extract_data!
|
173
|
-
@data ||= {}
|
195
|
+
@data ||= {}.with_indifferent_access
|
196
|
+
|
197
|
+
# Extract prefix and slug
|
198
|
+
if name =~ %r{\A([\d-]+)-(.+)\Z}
|
199
|
+
@prefix = $1
|
200
|
+
@slug = $2
|
201
|
+
else
|
202
|
+
@slug = name
|
203
|
+
end
|
174
204
|
|
175
|
-
#
|
176
|
-
|
205
|
+
# Change this node's name to the slug. This may be made optional
|
206
|
+
# in the future.
|
207
|
+
@name = @slug
|
208
|
+
|
209
|
+
# Extract date from prefix if possible
|
210
|
+
if prefix =~ %r{\A(\d\d\d\d\-\d\d?\-\d\d?)\Z}
|
177
211
|
@data['date'] = Date.parse($1)
|
178
212
|
end
|
179
213
|
|
180
214
|
# Read remaining data from frontmatter. Data in frontmatter
|
181
215
|
# will always have precedence!
|
182
|
-
|
216
|
+
extract_frontmatter!
|
183
217
|
|
184
|
-
# Do some extra processing depending on extension
|
218
|
+
# Do some extra processing depending on extension. This essentially
|
219
|
+
# means that your .json etc. files will be rendered at least once at
|
220
|
+
# bootup.
|
185
221
|
meth = "read_#{ext}!"
|
186
|
-
send(meth) if respond_to?(meth)
|
222
|
+
send(meth) if respond_to?(meth, true)
|
187
223
|
end
|
188
224
|
|
189
|
-
def
|
225
|
+
def extract_frontmatter!
|
190
226
|
@data || {}
|
191
227
|
|
192
228
|
if @source
|
@@ -203,11 +239,11 @@ module Flutterby
|
|
203
239
|
end
|
204
240
|
|
205
241
|
def read_json!
|
206
|
-
@data.merge!(JSON.parse(
|
242
|
+
@data.merge!(JSON.parse(render))
|
207
243
|
end
|
208
244
|
|
209
245
|
def read_yaml!
|
210
|
-
@data.merge!(YAML.load(
|
246
|
+
@data.merge!(YAML.load(render))
|
211
247
|
end
|
212
248
|
|
213
249
|
def read_yml!
|
@@ -215,85 +251,95 @@ module Flutterby
|
|
215
251
|
end
|
216
252
|
|
217
253
|
def read_toml!
|
218
|
-
@data.merge!(TOML.parse(
|
254
|
+
@data.merge!(TOML.parse(render))
|
219
255
|
end
|
220
256
|
end
|
221
257
|
|
222
|
-
|
258
|
+
include Reading
|
259
|
+
|
260
|
+
|
261
|
+
|
262
|
+
module Staging
|
223
263
|
def stage!
|
224
|
-
# First of all, we want to make sure all
|
225
|
-
#
|
264
|
+
# First of all, we want to make sure all initializers
|
265
|
+
# (`_init.rb` files) are executed, starting at the top of the tree.
|
226
266
|
#
|
227
|
-
walk_tree do |node|
|
228
|
-
|
267
|
+
TreeWalker.walk_tree(self) do |node|
|
268
|
+
if node.full_name == "_init.rb"
|
269
|
+
logger.debug "Executing initializer #{node.url}"
|
270
|
+
node.instance_eval(node.render)
|
271
|
+
end
|
229
272
|
end
|
230
273
|
|
231
|
-
#
|
232
|
-
#
|
274
|
+
# In a second pass, walk the tree to invoke any available
|
275
|
+
# setup methods.
|
233
276
|
#
|
234
|
-
walk_tree do |node|
|
235
|
-
node.
|
236
|
-
node.register_url! if node.should_publish?
|
277
|
+
TreeWalker.walk_tree(self) do |node|
|
278
|
+
node.perform_setup!
|
237
279
|
end
|
238
280
|
end
|
239
281
|
|
240
|
-
|
241
|
-
|
242
|
-
|
282
|
+
# Perform setup for this node. The setup step is run after the
|
283
|
+
# tree has been built up completely. It allows you to perform one-time
|
284
|
+
# setup operations that, for example, modify the tree (like sorting blog
|
285
|
+
# posts into date-specific subnodes.)
|
286
|
+
#
|
287
|
+
# Your nodes (or their extensions) may overload this method, but you
|
288
|
+
# may also simply use the `setup { ... }` syntax in a node extension
|
289
|
+
# to define a block of code to be run at setup time.
|
290
|
+
#
|
291
|
+
def perform_setup!
|
292
|
+
_setup_procs.each do |p|
|
293
|
+
instance_exec(&p)
|
243
294
|
end
|
244
295
|
end
|
245
296
|
|
246
|
-
|
247
|
-
|
248
|
-
|
297
|
+
# Extend all of this node's siblings. See {#extend_all}.
|
298
|
+
#
|
299
|
+
def extend_siblings(*mods, &blk)
|
300
|
+
extend_all(siblings, *mods, &blk)
|
249
301
|
end
|
250
|
-
end
|
251
302
|
|
252
|
-
|
253
|
-
|
254
|
-
def
|
255
|
-
|
303
|
+
# Extend this node's parent. See {#extend_all}.
|
304
|
+
#
|
305
|
+
def extend_parent(*mods, &blk)
|
306
|
+
extend_all([parent], *mods, &blk)
|
256
307
|
end
|
257
308
|
|
258
|
-
|
259
|
-
|
260
|
-
|
309
|
+
# Extend all of the specified `nodes` with the specified module(s). If
|
310
|
+
# a block is given, the nodes will be extended with the code found
|
311
|
+
# in the block.
|
312
|
+
#
|
313
|
+
def extend_all(nodes, *mods, &blk)
|
314
|
+
if block_given?
|
315
|
+
mods << NodeExtension.new(&blk)
|
261
316
|
end
|
262
317
|
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
def body
|
267
|
-
if @body.nil?
|
268
|
-
data # make sure data is lazy-loaded
|
269
|
-
render_body!
|
318
|
+
nodes.each do |n|
|
319
|
+
n.extend(*mods)
|
270
320
|
end
|
271
|
-
|
272
|
-
@body
|
273
321
|
end
|
322
|
+
end
|
274
323
|
|
275
|
-
|
276
|
-
layout = opts[:layout]
|
277
|
-
view.opts.merge!(opts)
|
278
|
-
(layout && apply_layout?) ? apply_layout(body) : body
|
279
|
-
end
|
324
|
+
include Staging
|
280
325
|
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
current
|
288
|
-
end
|
289
|
-
end
|
326
|
+
|
327
|
+
module Rendering
|
328
|
+
# Returns a freshly created {View} instance for this node.
|
329
|
+
#
|
330
|
+
def view(opts = {})
|
331
|
+
View.for(self, opts)
|
290
332
|
end
|
291
333
|
|
292
|
-
|
293
|
-
|
334
|
+
# Creates a new {View} instance through {#view} and uses it to
|
335
|
+
# render this node. Returns the rendered page as a string.
|
336
|
+
#
|
337
|
+
def render(opts = {})
|
338
|
+
view(opts).render!
|
294
339
|
end
|
295
340
|
end
|
296
341
|
|
342
|
+
include Rendering
|
297
343
|
|
298
344
|
|
299
345
|
|
@@ -302,8 +348,16 @@ module Flutterby
|
|
302
348
|
# Misc
|
303
349
|
#
|
304
350
|
|
351
|
+
# Returns the node's title. If there is a `:title` key in {#data}, its
|
352
|
+
# value will be used; otherwise, as a fallback, it will generate a
|
353
|
+
# human-readable title from {#slug}.
|
354
|
+
#
|
355
|
+
def title
|
356
|
+
data[:title] || slug.try(:titleize)
|
357
|
+
end
|
358
|
+
|
305
359
|
def to_s
|
306
|
-
"<#{self.class} #{self.
|
360
|
+
"<#{self.class} #{self.url}>"
|
307
361
|
end
|
308
362
|
|
309
363
|
def full_name
|
@@ -315,11 +369,11 @@ module Flutterby
|
|
315
369
|
end
|
316
370
|
|
317
371
|
def file?
|
318
|
-
!folder?
|
372
|
+
!folder? && should_publish?
|
319
373
|
end
|
320
374
|
|
321
375
|
def page?
|
322
|
-
|
376
|
+
file? && ext == "html"
|
323
377
|
end
|
324
378
|
|
325
379
|
def should_publish?
|
@@ -330,9 +384,10 @@ module Flutterby
|
|
330
384
|
Flutterby.logger
|
331
385
|
end
|
332
386
|
|
333
|
-
def copy(new_name)
|
387
|
+
def copy(new_name, data = {})
|
334
388
|
dup.tap do |c|
|
335
389
|
c.name = new_name
|
390
|
+
c.data.merge!(data)
|
336
391
|
parent.children << c
|
337
392
|
end
|
338
393
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Flutterby
|
2
|
+
# NodeExtension is a subclass of Module that also provides a convenient
|
3
|
+
# `setup` method for quick creation of initialization code. It's used
|
4
|
+
# to wrap the blocks of code passed to {Node#extend_all} and friends,
|
5
|
+
# but can also be used directly through `NodeExtension.new { ... }`.
|
6
|
+
#
|
7
|
+
class NodeExtension < Module
|
8
|
+
def initialize(*args)
|
9
|
+
@_setup_procs = []
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def extended(base)
|
14
|
+
if @_setup_procs.any?
|
15
|
+
base._setup_procs.append(*@_setup_procs)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def on_setup(&blk)
|
20
|
+
@_setup_procs << blk
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/flutterby/server.rb
CHANGED
@@ -4,12 +4,11 @@ require 'better_errors'
|
|
4
4
|
|
5
5
|
module Flutterby
|
6
6
|
class Server
|
7
|
-
def initialize(root
|
7
|
+
def initialize(root)
|
8
8
|
@root = root
|
9
|
-
@port = port
|
10
9
|
end
|
11
10
|
|
12
|
-
def run!
|
11
|
+
def run!(port: 4004)
|
13
12
|
# Set up listener
|
14
13
|
listener = Listen.to(@root.fs_path) do |modified, added, removed|
|
15
14
|
# puts "modified absolute path: #{modified}"
|
@@ -40,11 +39,11 @@ module Flutterby
|
|
40
39
|
|
41
40
|
# Go!
|
42
41
|
listener.start
|
43
|
-
server.run app, Port:
|
42
|
+
server.run app, Port: port, Logger: Flutterby.logger
|
44
43
|
end
|
45
44
|
|
46
45
|
def call(env)
|
47
|
-
req
|
46
|
+
req = Rack::Request.new(env)
|
48
47
|
res = Rack::Response.new([], 200, {})
|
49
48
|
|
50
49
|
# Look for target node in path registry
|
@@ -65,9 +64,11 @@ module Flutterby
|
|
65
64
|
end
|
66
65
|
|
67
66
|
def find_node_for_path(path)
|
68
|
-
@root.
|
69
|
-
|
70
|
-
|
67
|
+
if node = @root.find(path, public_only: true)
|
68
|
+
# If the node is a folder, try and find its "index" node.
|
69
|
+
# Otherwise, use the node directly.
|
70
|
+
node.folder? ? node.find('index') : node
|
71
|
+
end
|
71
72
|
end
|
72
73
|
end
|
73
74
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Flutterby
|
2
|
+
# A helper module with methods to walk across a node tree in various
|
3
|
+
# directions and variations and perform a block of code on each passed node.
|
4
|
+
#
|
5
|
+
module TreeWalker
|
6
|
+
extend self
|
7
|
+
|
8
|
+
# Walk the tree up, invoking the passed block for every node
|
9
|
+
# found on the way, passing the node as its only argument.
|
10
|
+
#
|
11
|
+
def walk_up(node, val = nil, &blk)
|
12
|
+
val = blk.call(node, val)
|
13
|
+
node.parent ? walk_up(node.parent, val, &blk) : val
|
14
|
+
end
|
15
|
+
|
16
|
+
# Walk the graph from the root to the specified node. Just like {#walk_up},
|
17
|
+
# except the block will be called on higher level nodes first.
|
18
|
+
#
|
19
|
+
def walk_down(node, val = nil, &blk)
|
20
|
+
val = node.parent ? walk_up(node.parent, val, &blk) : val
|
21
|
+
blk.call(node, val)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Walk the entire tree, top to bottom, starting with its root, and then
|
25
|
+
# descending into its child layers.
|
26
|
+
#
|
27
|
+
def walk_tree(node, val = nil, &blk)
|
28
|
+
val = blk.call(node, val)
|
29
|
+
|
30
|
+
node.children.each do |child|
|
31
|
+
val = walk_tree(child, val, &blk)
|
32
|
+
end
|
33
|
+
|
34
|
+
val
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/flutterby/version.rb
CHANGED
data/lib/flutterby/view.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
|
1
3
|
module Flutterby
|
2
4
|
class View
|
3
|
-
attr_reader :node, :opts
|
5
|
+
attr_reader :node, :opts, :source
|
6
|
+
attr_accessor :_body
|
4
7
|
alias_method :page, :node
|
5
8
|
|
6
9
|
# Include ERB::Util from ActiveSupport. This will provide
|
@@ -10,9 +13,41 @@ module Flutterby
|
|
10
13
|
#
|
11
14
|
include ERB::Util
|
12
15
|
|
13
|
-
def initialize(node)
|
16
|
+
def initialize(node, opts = {})
|
14
17
|
@node = node
|
15
|
-
@opts =
|
18
|
+
@opts = opts
|
19
|
+
@source = node.source
|
20
|
+
@_body = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def render!
|
24
|
+
time = Benchmark.realtime do
|
25
|
+
Filters.apply!(self)
|
26
|
+
|
27
|
+
# Apply layouts
|
28
|
+
if opts[:layout] && node.page?
|
29
|
+
@_body = apply_layout!(@_body)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
logger.info "Rendered #{node.url} in #{sprintf "%.1f", time * 1000}ms"
|
34
|
+
|
35
|
+
@_body
|
36
|
+
end
|
37
|
+
|
38
|
+
def apply_layout!(input)
|
39
|
+
TreeWalker.walk_up(node, input) do |node, current|
|
40
|
+
if layout = node.sibling("_layout")
|
41
|
+
tilt = Flutterby::Filters.tilt(layout.ext, layout.source)
|
42
|
+
tilt.render(self) { current }.html_safe
|
43
|
+
else
|
44
|
+
current
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_s
|
50
|
+
@_body ||= render!
|
16
51
|
end
|
17
52
|
|
18
53
|
def date_format(date, fmt)
|
@@ -24,7 +59,11 @@ module Flutterby
|
|
24
59
|
end
|
25
60
|
|
26
61
|
def render(expr, *args)
|
27
|
-
|
62
|
+
if expr.is_a?(Node)
|
63
|
+
expr.render(*args)
|
64
|
+
else
|
65
|
+
find(expr).render(*args)
|
66
|
+
end
|
28
67
|
end
|
29
68
|
|
30
69
|
def find(*args)
|
@@ -35,7 +74,7 @@ module Flutterby
|
|
35
74
|
node.siblings(*args)
|
36
75
|
end
|
37
76
|
|
38
|
-
def tag(name, attributes)
|
77
|
+
def tag(name, attributes = {})
|
39
78
|
ActiveSupport::SafeBuffer.new.tap do |output|
|
40
79
|
attributes_str = attributes.keys.sort.map do |k|
|
41
80
|
%{#{h k}="#{h attributes[k]}"}
|
@@ -61,16 +100,20 @@ module Flutterby
|
|
61
100
|
tag(:pre, class: "debug") { h obj.to_yaml }
|
62
101
|
end
|
63
102
|
|
103
|
+
def logger
|
104
|
+
@logger ||= Flutterby.logger
|
105
|
+
end
|
106
|
+
|
64
107
|
class << self
|
65
108
|
# Factory method that returns a newly created view for the given node.
|
66
109
|
# It also makes sure all available _view.rb extensions are loaded.
|
67
110
|
#
|
68
|
-
def for(
|
111
|
+
def for(node, *args)
|
69
112
|
# create a new view instance
|
70
|
-
view = new(
|
113
|
+
view = new(node, *args)
|
71
114
|
|
72
115
|
# walk the tree up to dynamically extend the view
|
73
|
-
|
116
|
+
TreeWalker.walk_down(node) do |e|
|
74
117
|
if view_node = e.sibling("_view.rb")
|
75
118
|
case view_node.ext
|
76
119
|
when "rb" then
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# This is your site's configuration file.
|
2
|
+
|
3
|
+
site:
|
4
|
+
title: My Flutterby Site
|
5
|
+
description: >
|
6
|
+
This is my new <a href="https://github.com/hmans/flutterby">Flutterby</a> Site. I should probably
|
7
|
+
change this description in my site's configuration file,
|
8
|
+
found at ./site/_config.yaml. Or I can just leave it as is.
|
9
|
+
Isn't choice wonderful?
|
@@ -2,7 +2,8 @@ doctype html
|
|
2
2
|
html
|
3
3
|
head
|
4
4
|
meta charset="utf-8"
|
5
|
-
title = config
|
5
|
+
title = config.site.title
|
6
|
+
meta name="viewport" content="width=device-width, initial-scale=1.0"
|
6
7
|
|
7
8
|
// highlight.js for syntax highlighting
|
8
9
|
link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.9.0/styles/default.min.css"
|
@@ -17,4 +18,4 @@ html
|
|
17
18
|
= yield
|
18
19
|
|
19
20
|
footer role="main"
|
20
|
-
== config
|
21
|
+
== config.site.description
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# A _init.rb file contains Ruby code that will be executed when
|
2
|
+
# your application boots up. Use it to extend and modify other nodes!
|
3
|
+
#
|
4
|
+
# In this simple example, we're simply adding some convenience methods to
|
5
|
+
# all available blog posts for easier access to specific pieces of data.
|
6
|
+
|
7
|
+
extend_siblings do
|
8
|
+
def date
|
9
|
+
data.date
|
10
|
+
end
|
11
|
+
end
|
@@ -8,7 +8,7 @@ date: <%= Date.today.to_s %>
|
|
8
8
|
|
9
9
|
This sample project is set up as a simple blog, but of course you can do so much more with Flutterby. Just head straight into your project's `site` directory and mix things up. Some files you should look at:
|
10
10
|
|
11
|
-
| `/_config.
|
11
|
+
| `/_config.yaml` | Your site configuration. |
|
12
12
|
| `/css/styles.css.scss` | Your stylesheet. [Sass]-powered, of course! |
|
13
13
|
| `/_layout.slim` | Your global site layout. |
|
14
14
|
| `/posts/_layout.slim` | Your post-specific layout. |
|
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.5.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-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0.10'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: yard
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.9'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.9'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: erubis
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -343,6 +357,7 @@ files:
|
|
343
357
|
- ".gitignore"
|
344
358
|
- ".rspec"
|
345
359
|
- ".travis.yml"
|
360
|
+
- ".yardopts"
|
346
361
|
- CHANGES.md
|
347
362
|
- Gemfile
|
348
363
|
- LICENSE.txt
|
@@ -352,28 +367,34 @@ files:
|
|
352
367
|
- bin/rake
|
353
368
|
- bin/rspec
|
354
369
|
- bin/setup
|
370
|
+
- bin/yard
|
371
|
+
- bin/yardoc
|
372
|
+
- bin/yri
|
355
373
|
- exe/flutterby
|
356
374
|
- flutterby.gemspec
|
357
375
|
- lib/flutterby.rb
|
358
376
|
- lib/flutterby/cli.rb
|
377
|
+
- lib/flutterby/dotaccess.rb
|
359
378
|
- lib/flutterby/exporter.rb
|
360
379
|
- lib/flutterby/filters.rb
|
361
380
|
- lib/flutterby/markdown_formatter.rb
|
362
381
|
- lib/flutterby/node.rb
|
382
|
+
- lib/flutterby/node_extension.rb
|
363
383
|
- lib/flutterby/server.rb
|
384
|
+
- lib/flutterby/tree_walker.rb
|
364
385
|
- lib/flutterby/version.rb
|
365
386
|
- lib/flutterby/view.rb
|
366
387
|
- lib/templates/new_project/.gitignore
|
367
388
|
- lib/templates/new_project/Gemfile.tt
|
368
389
|
- lib/templates/new_project/README.md
|
369
390
|
- lib/templates/new_project/bin/flutterby
|
370
|
-
- lib/templates/new_project/site/_config.
|
391
|
+
- lib/templates/new_project/site/_config.yaml
|
371
392
|
- lib/templates/new_project/site/_layout.slim
|
372
393
|
- lib/templates/new_project/site/_view.rb
|
373
394
|
- lib/templates/new_project/site/about.html.md
|
395
|
+
- lib/templates/new_project/site/blog/_init.rb
|
374
396
|
- lib/templates/new_project/site/blog/_layout.slim
|
375
397
|
- lib/templates/new_project/site/blog/_list.html.slim
|
376
|
-
- lib/templates/new_project/site/blog/_node.rb
|
377
398
|
- lib/templates/new_project/site/blog/_view.rb
|
378
399
|
- lib/templates/new_project/site/blog/hello-world.html.md.tt
|
379
400
|
- lib/templates/new_project/site/css/styles.css.scss
|
@@ -1,10 +0,0 @@
|
|
1
|
-
# This is your site's configuration file.
|
2
|
-
|
3
|
-
[site]
|
4
|
-
title = "My Flutterby Site"
|
5
|
-
description = """
|
6
|
-
This is my new <a href="https://github.com/hmans/flutterby">Flutterby</a> Site. I should probably
|
7
|
-
change this description in my site's configuration file,
|
8
|
-
found at ./site/_config.toml. Or I can just leave it as is.
|
9
|
-
Isn't choice wonderful?
|
10
|
-
"""
|
@@ -1,14 +0,0 @@
|
|
1
|
-
# A _node.rb will be run against all nodes from the same directory -- use it
|
2
|
-
# to enhance the Ruby objects representing these nodes with extra methods
|
3
|
-
# or behavior.
|
4
|
-
#
|
5
|
-
# In this example, we're simply adding some convenience methods for easier
|
6
|
-
# access to specific pieces of data.
|
7
|
-
|
8
|
-
def date
|
9
|
-
data["date"]
|
10
|
-
end
|
11
|
-
|
12
|
-
def title
|
13
|
-
data["title"]
|
14
|
-
end
|