flutterby 0.3.1 → 0.4.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/CHANGES.md +7 -0
- data/README.md +4 -17
- data/lib/flutterby/cli.rb +2 -1
- data/lib/flutterby/node.rb +200 -208
- data/lib/flutterby/version.rb +1 -1
- data/lib/flutterby/view.rb +26 -0
- data/lib/templates/new_project/{Gemfile → Gemfile.tt} +1 -1
- data/lib/templates/new_project/site/_layout.slim +1 -1
- data/lib/templates/new_project/site/blog/_list.html.slim +1 -2
- data/lib/templates/new_project/site/blog/{2017-01-01-hello-world.html.md → hello-world.html.md.tt} +1 -0
- data/lib/templates/new_project/site/index.html.slim +1 -1
- metadata +4 -4
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 83e24d1e73103a5cef7b60efcf5a21951e474c66
         | 
| 4 | 
            +
              data.tar.gz: f25f5763a2a10b7190e9ea5a827ef716bba729f7
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: fc8ecf0efc0a1615d0149b1a94b0eb3fef7cd27db54147de26238646313f2dc679b74335cc69671364f1d04f43c96d72112ff7b596a27c883256808449622aa4
         | 
| 7 | 
            +
              data.tar.gz: d7ed0d77dde3726cc718c0420f1d1f3a5732c17a9906329d945b7eb607ccce3fa183659a7b92787edcb024bb39883f04cbcf6982a43675da21be31b576ba860d
         | 
    
        data/CHANGES.md
    CHANGED
    
    | @@ -1,5 +1,12 @@ | |
| 1 1 | 
             
            # Version History
         | 
| 2 2 |  | 
| 3 | 
            +
            ### 0.4.0 (2017-01-21)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            - **NEW:** Flutterby views now have a `tag` helper method available that can generate HTML tags programatically.
         | 
| 6 | 
            +
            - **NEW:** Flutterby views now have a `link_to` helper method available that renders link tags. You can use a URL string as the link target, eg. `link_to "Home", "/"`, or any Flutterby node, eg. `link_to "Blog", blog_node`.
         | 
| 7 | 
            +
            - **NEW:** Flutterby views now have a `debug` helper that will dump its argument's YAML representation into a `<pre>` HTML tag (similar to Rails.)
         | 
| 8 | 
            +
             | 
| 9 | 
            +
             | 
| 3 10 | 
             
            ### 0.3.1 (2017-01-15)
         | 
| 4 11 |  | 
| 5 12 | 
             
            - **NEW:** Flutterby now uses ActiveSupport. It's a big dependency, but there's just so much useful goodness in there -- let's ride on the shoulders of that giant! This allows you to use all the neat little ActiveSupport toys you may know from Rails in your Flutterby project.
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            # Flutterby
         | 
| 2 2 |  | 
| 3 | 
            -
            ### A  | 
| 3 | 
            +
            ### A flexible, Ruby-powered static site generator.
         | 
| 4 4 |  | 
| 5 5 | 
             
            [](https://badge.fury.io/rb/flutterby) [](https://travis-ci.org/hmans/flutterby) [](https://github.com/hmans/flutterby/blob/master/LICENSE.txt) 
         | 
| 6 6 |  | 
| @@ -18,6 +18,9 @@ | |
| 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 20 | 
             
            - [Version History](https://github.com/hmans/flutterby/blob/master/CHANGES.md)
         | 
| 21 | 
            +
            - [Roadmap](https://github.com/hmans/flutterby/projects/1)
         | 
| 22 | 
            +
            - [Sites built with Flutterby](https://github.com/hmans/flutterby/wiki/Sites-built-with-Flutterby) (add yours!)
         | 
| 23 | 
            +
             | 
| 21 24 |  | 
| 22 25 | 
             
            ## Installation & Basic Usage
         | 
| 23 26 |  | 
| @@ -41,22 +44,6 @@ Flutterby comes with a local development server that will automatically pick up | |
| 41 44 | 
             
            **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.
         | 
| 42 45 |  | 
| 43 46 |  | 
| 44 | 
            -
            ## Examples
         | 
| 45 | 
            -
             | 
| 46 | 
            -
            Please refer to the [Sites built with Flutterby](https://github.com/hmans/flutterby/wiki/Sites-built-with-Flutterby) page on the Flutterby Wiki for some examples.
         | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
            ## Roadmap
         | 
| 50 | 
            -
             | 
| 51 | 
            -
            Flutterby is young, but already quite functional. Here's a list of changes I'm intending to make in the near future -- if you want to work on any of these, let me know!
         | 
| 52 | 
            -
             | 
| 53 | 
            -
            - Performance! Right now, the source file for every node is read into RAM as a whole. Not a big problem when you're building a small site, but add some larger images, and you'll have one.
         | 
| 54 | 
            -
            - Change `flutterby serve` so it doesn't always regenerate the _entire_ site graph when a file is modified.
         | 
| 55 | 
            -
            - Extract filters (like Slim, Sass etc.) to separate gems, to make the core gem more light-weight.
         | 
| 56 | 
            -
            - Improve the template site (`flutterby new`).
         | 
| 57 | 
            -
            - Produce a fun screencast to explain what the heck is going on here!
         | 
| 58 | 
            -
            - Write even more tests!
         | 
| 59 | 
            -
             | 
| 60 47 |  | 
| 61 48 | 
             
            ## Notes
         | 
| 62 49 |  | 
    
        data/lib/flutterby/cli.rb
    CHANGED
    
    | @@ -60,7 +60,7 @@ module Flutterby | |
| 60 60 | 
             
                  root.stage!
         | 
| 61 61 | 
             
                  say color("🌲  Read #{root.tree_size} nodes.", :green, :bold)
         | 
| 62 62 |  | 
| 63 | 
            -
                  say color("🌤  Serving your site on  | 
| 63 | 
            +
                  say color("🌤  Serving your Flutterby site on http://localhost:#{options.port} - enjoy! \\o/", :bold)
         | 
| 64 64 | 
             
                  server = Flutterby::Server.new(root, port: options.port)
         | 
| 65 65 | 
             
                  server.run!
         | 
| 66 66 | 
             
                end
         | 
| @@ -75,6 +75,7 @@ module Flutterby | |
| 75 75 |  | 
| 76 76 | 
             
                  say color("🏗  Creating a new Flutterby project in #{path}...", :bold)
         | 
| 77 77 | 
             
                  directory("new_project", path)
         | 
| 78 | 
            +
                  chmod("bin/flutterby", 0755)
         | 
| 78 79 | 
             
                  in_root { bundle_install }
         | 
| 79 80 | 
             
                end
         | 
| 80 81 |  | 
    
        data/lib/flutterby/node.rb
    CHANGED
    
    | @@ -2,7 +2,8 @@ require 'benchmark' | |
| 2 2 |  | 
| 3 3 | 
             
            module Flutterby
         | 
| 4 4 | 
             
              class Node
         | 
| 5 | 
            -
                attr_accessor :name, :ext, :source | 
| 5 | 
            +
                attr_accessor :name, :ext, :source
         | 
| 6 | 
            +
                attr_writer :body
         | 
| 6 7 | 
             
                attr_reader :filters, :parent, :fs_path, :children, :paths
         | 
| 7 8 |  | 
| 8 9 | 
             
                def initialize(name, parent: nil, fs_path: nil, source: nil)
         | 
| @@ -23,287 +24,278 @@ module Flutterby | |
| 23 24 | 
             
                  reload!
         | 
| 24 25 | 
             
                end
         | 
| 25 26 |  | 
| 26 | 
            -
                 | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
                  if file? && should_publish?
         | 
| 32 | 
            -
                    root.paths[url] = self
         | 
| 27 | 
            +
                concerning :Children do
         | 
| 28 | 
            +
                  def register_url!
         | 
| 29 | 
            +
                    if file? && should_publish?
         | 
| 30 | 
            +
                      root.paths[url] = self
         | 
| 31 | 
            +
                    end
         | 
| 33 32 | 
             
                  end
         | 
| 34 | 
            -
                end
         | 
| 35 33 |  | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
                end
         | 
| 43 | 
            -
             | 
| 44 | 
            -
                def tree_size
         | 
| 45 | 
            -
                  children.inject(children.length) do |count, child|
         | 
| 46 | 
            -
                    count + child.tree_size
         | 
| 34 | 
            +
                  def find_child(name)
         | 
| 35 | 
            +
                    if name.include?(".")
         | 
| 36 | 
            +
                      @children.find { |c| c.full_name == name }
         | 
| 37 | 
            +
                    else
         | 
| 38 | 
            +
                      @children.find { |c| c.name == name }
         | 
| 39 | 
            +
                    end
         | 
| 47 40 | 
             
                  end
         | 
| 48 | 
            -
                end
         | 
| 49 41 |  | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 42 | 
            +
                  def tree_size
         | 
| 43 | 
            +
                    children.inject(children.length) do |count, child|
         | 
| 44 | 
            +
                      count + child.tree_size
         | 
| 45 | 
            +
                    end
         | 
| 53 46 | 
             
                  end
         | 
| 54 47 |  | 
| 55 | 
            -
                   | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
                # Returns all children that will compile to a HTML page.
         | 
| 61 | 
            -
                #
         | 
| 62 | 
            -
                def pages
         | 
| 63 | 
            -
                  children.select { |c| c.ext == "html" && c.should_publish? }
         | 
| 64 | 
            -
                end
         | 
| 65 | 
            -
             | 
| 66 | 
            -
                #
         | 
| 67 | 
            -
                # Path Algebra
         | 
| 68 | 
            -
                #
         | 
| 69 | 
            -
             | 
| 70 | 
            -
                def path
         | 
| 71 | 
            -
                  parent ? ::File.join(parent.path, full_name) : full_name
         | 
| 72 | 
            -
                end
         | 
| 73 | 
            -
             | 
| 74 | 
            -
                def url
         | 
| 75 | 
            -
                  ::File.join(parent ? parent.url : "/", full_name)
         | 
| 76 | 
            -
                end
         | 
| 77 | 
            -
             | 
| 78 | 
            -
                def full_fs_path(base:)
         | 
| 79 | 
            -
                  ::File.expand_path(::File.join(base, full_name))
         | 
| 80 | 
            -
                end
         | 
| 48 | 
            +
                  def parent=(new_parent)
         | 
| 49 | 
            +
                    if @parent
         | 
| 50 | 
            +
                      @parent.children.delete(self)
         | 
| 51 | 
            +
                    end
         | 
| 81 52 |  | 
| 53 | 
            +
                    @parent = new_parent
         | 
| 82 54 |  | 
| 83 | 
            -
             | 
| 84 | 
            -
             | 
| 85 | 
            -
                #
         | 
| 55 | 
            +
                    @parent.children << self
         | 
| 56 | 
            +
                  end
         | 
| 86 57 |  | 
| 87 | 
            -
             | 
| 88 | 
            -
                   | 
| 58 | 
            +
                  # Returns all children that will compile to a HTML page.
         | 
| 59 | 
            +
                  #
         | 
| 60 | 
            +
                  def pages
         | 
| 61 | 
            +
                    children.select { |c| c.ext == "html" && c.should_publish? }
         | 
| 62 | 
            +
                  end
         | 
| 89 63 | 
             
                end
         | 
| 90 64 |  | 
| 91 | 
            -
                 | 
| 92 | 
            -
                   | 
| 93 | 
            -
             | 
| 65 | 
            +
                concerning :Paths do
         | 
| 66 | 
            +
                  def path
         | 
| 67 | 
            +
                    parent ? ::File.join(parent.path, full_name) : full_name
         | 
| 68 | 
            +
                  end
         | 
| 94 69 |  | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 70 | 
            +
                  def url
         | 
| 71 | 
            +
                    ::File.join(parent ? parent.url : "/", full_name)
         | 
| 72 | 
            +
                  end
         | 
| 98 73 |  | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 74 | 
            +
                  def full_fs_path(base:)
         | 
| 75 | 
            +
                    ::File.expand_path(::File.join(base, full_name))
         | 
| 76 | 
            +
                  end
         | 
| 101 77 | 
             
                end
         | 
| 102 78 |  | 
| 103 | 
            -
                def find(path)
         | 
| 104 | 
            -
                  return self if path.nil? || path.empty?
         | 
| 105 | 
            -
             | 
| 106 | 
            -
                  # remove duplicate slashes
         | 
| 107 | 
            -
                  path.gsub!(%r{/+}, "/")
         | 
| 108 79 |  | 
| 109 | 
            -
             | 
| 110 | 
            -
                   | 
| 111 | 
            -
                    parent ? parent. | 
| 112 | 
            -
                  when %r{^/} then
         | 
| 113 | 
            -
                    root.find($')
         | 
| 114 | 
            -
                  when %r{^([^/]+)/?} then
         | 
| 115 | 
            -
                    child = find_child($1)
         | 
| 116 | 
            -
                    $'.empty? ? child : child.find($')
         | 
| 80 | 
            +
                concerning :Tree do
         | 
| 81 | 
            +
                  def root
         | 
| 82 | 
            +
                    parent ? parent.root : self
         | 
| 117 83 | 
             
                  end
         | 
| 118 | 
            -
                end
         | 
| 119 84 |  | 
| 120 | 
            -
             | 
| 121 | 
            -
             | 
| 122 | 
            -
             | 
| 123 | 
            -
                def walk_up(val = nil, &blk)
         | 
| 124 | 
            -
                  val = blk.call(self, val)
         | 
| 125 | 
            -
                  parent ? parent.walk_up(val, &blk) : val
         | 
| 126 | 
            -
                end
         | 
| 85 | 
            +
                  def root?
         | 
| 86 | 
            +
                    root == self
         | 
| 87 | 
            +
                  end
         | 
| 127 88 |  | 
| 128 | 
            -
             | 
| 129 | 
            -
             | 
| 130 | 
            -
             | 
| 131 | 
            -
                def walk_down(val = nil, &blk)
         | 
| 132 | 
            -
                  val = parent ? parent.walk_up(val, &blk) : val
         | 
| 133 | 
            -
                  blk.call(self, val)
         | 
| 134 | 
            -
                end
         | 
| 89 | 
            +
                  def sibling(name)
         | 
| 90 | 
            +
                    parent && parent.find(name)
         | 
| 91 | 
            +
                  end
         | 
| 135 92 |  | 
| 136 | 
            -
             | 
| 137 | 
            -
             | 
| 138 | 
            -
                def walk_tree(val = nil, &blk)
         | 
| 139 | 
            -
                  val = blk.call(self, val)
         | 
| 140 | 
            -
                  children.each do |child|
         | 
| 141 | 
            -
                    val = child.walk_tree(val, &blk)
         | 
| 93 | 
            +
                  def siblings
         | 
| 94 | 
            +
                    parent && parent.children
         | 
| 142 95 | 
             
                  end
         | 
| 143 96 |  | 
| 144 | 
            -
                   | 
| 145 | 
            -
             | 
| 97 | 
            +
                  def find(path)
         | 
| 98 | 
            +
                    return self if path.nil? || path.empty?
         | 
| 146 99 |  | 
| 147 | 
            -
             | 
| 148 | 
            -
             | 
| 149 | 
            -
                #
         | 
| 100 | 
            +
                    # remove duplicate slashes
         | 
| 101 | 
            +
                    path.gsub!(%r{/+}, "/")
         | 
| 150 102 |  | 
| 151 | 
            -
             | 
| 152 | 
            -
             | 
| 153 | 
            -
             | 
| 154 | 
            -
             | 
| 155 | 
            -
             | 
| 103 | 
            +
                    case path
         | 
| 104 | 
            +
                    when %r{^\./?} then
         | 
| 105 | 
            +
                      parent ? parent.find($') : root.find($')
         | 
| 106 | 
            +
                    when %r{^/} then
         | 
| 107 | 
            +
                      root.find($')
         | 
| 108 | 
            +
                    when %r{^([^/]+)/?} then
         | 
| 109 | 
            +
                      child = find_child($1)
         | 
| 110 | 
            +
                      $'.empty? ? child : child.find($')
         | 
| 111 | 
            +
                    end
         | 
| 112 | 
            +
                  end
         | 
| 156 113 |  | 
| 157 | 
            -
                   | 
| 158 | 
            -
             | 
| 114 | 
            +
                  # Walk the tree up, invoking the passed block for every node
         | 
| 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
         | 
| 159 121 |  | 
| 160 | 
            -
             | 
| 161 | 
            -
                  #  | 
| 162 | 
            -
                  # available extensions loaded.
         | 
| 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.
         | 
| 163 124 | 
             
                  #
         | 
| 164 | 
            -
                   | 
| 165 | 
            -
                     | 
| 125 | 
            +
                  def walk_down(val = nil, &blk)
         | 
| 126 | 
            +
                    val = parent ? parent.walk_up(val, &blk) : val
         | 
| 127 | 
            +
                    blk.call(self, val)
         | 
| 166 128 | 
             
                  end
         | 
| 167 129 |  | 
| 168 | 
            -
                  #  | 
| 169 | 
            -
                  # extracting data, registering URLs to be exported, etc.
         | 
| 130 | 
            +
                  # Walk the entire tree, top to bottom.
         | 
| 170 131 | 
             
                  #
         | 
| 171 | 
            -
                  walk_tree  | 
| 172 | 
            -
                     | 
| 173 | 
            -
                     | 
| 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
         | 
| 174 139 | 
             
                  end
         | 
| 175 140 | 
             
                end
         | 
| 176 141 |  | 
| 177 | 
            -
                 | 
| 178 | 
            -
                  ! | 
| 179 | 
            -
                     | 
| 180 | 
            -
             | 
| 142 | 
            +
                concerning :Reading do
         | 
| 143 | 
            +
                  def reload!
         | 
| 144 | 
            +
                    @body     = nil
         | 
| 145 | 
            +
                    @data     = nil
         | 
| 146 | 
            +
                    @children = []
         | 
| 147 | 
            +
                    @paths    = {}
         | 
| 181 148 |  | 
| 182 | 
            -
             | 
| 183 | 
            -
                   | 
| 184 | 
            -
             | 
| 185 | 
            -
             | 
| 186 | 
            -
             | 
| 187 | 
            -
             | 
| 149 | 
            +
                    load_from_filesystem! if @fs_path
         | 
| 150 | 
            +
                  end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                  def load_from_filesystem!
         | 
| 153 | 
            +
                    if @fs_path
         | 
| 154 | 
            +
                      if ::File.directory?(fs_path)
         | 
| 155 | 
            +
                        Dir[::File.join(fs_path, "*")].each do |entry|
         | 
| 156 | 
            +
                          name = ::File.basename(entry)
         | 
| 157 | 
            +
                          Flutterby::Node.new(name, parent: self, fs_path: entry)
         | 
| 158 | 
            +
                        end
         | 
| 159 | 
            +
                      else
         | 
| 160 | 
            +
                        @source = ::File.read(fs_path)
         | 
| 188 161 | 
             
                      end
         | 
| 189 | 
            -
                    else
         | 
| 190 | 
            -
                      @source = ::File.read(fs_path)
         | 
| 191 162 | 
             
                    end
         | 
| 192 163 | 
             
                  end
         | 
| 193 164 | 
             
                end
         | 
| 194 165 |  | 
| 195 | 
            -
                 | 
| 196 | 
            -
                   | 
| 197 | 
            -
             | 
| 198 | 
            -
             | 
| 199 | 
            -
                  if name =~ %r{^(\d\d\d\d\-\d\d?\-\d\d?)\-}
         | 
| 200 | 
            -
                    @data['date'] = Date.parse($1)
         | 
| 166 | 
            +
                concerning :Data do
         | 
| 167 | 
            +
                  def data
         | 
| 168 | 
            +
                    extract_data! if @data.nil?
         | 
| 169 | 
            +
                    @data
         | 
| 201 170 | 
             
                  end
         | 
| 202 171 |  | 
| 203 | 
            -
                   | 
| 204 | 
            -
             | 
| 205 | 
            -
                  parse_frontmatter!
         | 
| 172 | 
            +
                  def extract_data!
         | 
| 173 | 
            +
                    @data ||= {}
         | 
| 206 174 |  | 
| 207 | 
            -
             | 
| 208 | 
            -
             | 
| 209 | 
            -
             | 
| 210 | 
            -
             | 
| 175 | 
            +
                    # Extract date from name
         | 
| 176 | 
            +
                    if name =~ %r{^(\d\d\d\d\-\d\d?\-\d\d?)\-}
         | 
| 177 | 
            +
                      @data['date'] = Date.parse($1)
         | 
| 178 | 
            +
                    end
         | 
| 211 179 |  | 
| 212 | 
            -
             | 
| 213 | 
            -
             | 
| 214 | 
            -
                     | 
| 180 | 
            +
                    # Read remaining data from frontmatter. Data in frontmatter
         | 
| 181 | 
            +
                    # will always have precedence!
         | 
| 182 | 
            +
                    parse_frontmatter!
         | 
| 183 | 
            +
             | 
| 184 | 
            +
                    # Do some extra processing depending on extension
         | 
| 185 | 
            +
                    meth = "read_#{ext}!"
         | 
| 186 | 
            +
                    send(meth) if respond_to?(meth)
         | 
| 215 187 | 
             
                  end
         | 
| 216 | 
            -
                end
         | 
| 217 188 |  | 
| 218 | 
            -
             | 
| 219 | 
            -
             | 
| 220 | 
            -
                #
         | 
| 189 | 
            +
                  def parse_frontmatter!
         | 
| 190 | 
            +
                    @data || {}
         | 
| 221 191 |  | 
| 222 | 
            -
             | 
| 223 | 
            -
             | 
| 224 | 
            -
             | 
| 192 | 
            +
                    if @source
         | 
| 193 | 
            +
                      # YAML Front Matter
         | 
| 194 | 
            +
                      if @source.sub!(/\A\-\-\-\n(.+)\n\-\-\-\n/m, "")
         | 
| 195 | 
            +
                        @data.merge! YAML.load($1)
         | 
| 196 | 
            +
                      end
         | 
| 225 197 |  | 
| 226 | 
            -
             | 
| 227 | 
            -
             | 
| 228 | 
            -
             | 
| 198 | 
            +
                      # TOML Front Matter
         | 
| 199 | 
            +
                      if @source.sub!(/\A\+\+\+\n(.+)\n\+\+\+\n/m, "")
         | 
| 200 | 
            +
                        @data.merge! TOML.parse($1)
         | 
| 201 | 
            +
                      end
         | 
| 202 | 
            +
                    end
         | 
| 229 203 | 
             
                  end
         | 
| 230 204 |  | 
| 231 | 
            -
                   | 
| 232 | 
            -
             | 
| 205 | 
            +
                  def read_json!
         | 
| 206 | 
            +
                    @data.merge!(JSON.parse(body))
         | 
| 207 | 
            +
                  end
         | 
| 233 208 |  | 
| 234 | 
            -
             | 
| 235 | 
            -
             | 
| 236 | 
            -
                    data   # make sure data is lazy-loaded
         | 
| 237 | 
            -
                    render_body!
         | 
| 209 | 
            +
                  def read_yaml!
         | 
| 210 | 
            +
                    @data.merge!(YAML.load(body))
         | 
| 238 211 | 
             
                  end
         | 
| 239 212 |  | 
| 240 | 
            -
                   | 
| 241 | 
            -
             | 
| 213 | 
            +
                  def read_yml!
         | 
| 214 | 
            +
                    read_yaml!
         | 
| 215 | 
            +
                  end
         | 
| 242 216 |  | 
| 243 | 
            -
             | 
| 244 | 
            -
             | 
| 245 | 
            -
                   | 
| 217 | 
            +
                  def read_toml!
         | 
| 218 | 
            +
                    @data.merge!(TOML.parse(body))
         | 
| 219 | 
            +
                  end
         | 
| 246 220 | 
             
                end
         | 
| 247 221 |  | 
| 248 | 
            -
                 | 
| 249 | 
            -
                   | 
| 250 | 
            -
             | 
| 251 | 
            -
             | 
| 252 | 
            -
             | 
| 222 | 
            +
                concerning :Staging do
         | 
| 223 | 
            +
                  def stage!
         | 
| 224 | 
            +
                    # First of all, we want to make sure all nodes have their
         | 
| 225 | 
            +
                    # available extensions loaded.
         | 
| 226 | 
            +
                    #
         | 
| 227 | 
            +
                    walk_tree do |node|
         | 
| 228 | 
            +
                      node.load_extension! unless node.name == "_node"
         | 
| 229 | 
            +
                    end
         | 
| 253 230 |  | 
| 254 | 
            -
             | 
| 255 | 
            -
             | 
| 256 | 
            -
                     | 
| 257 | 
            -
             | 
| 258 | 
            -
                       | 
| 259 | 
            -
             | 
| 260 | 
            -
                      current
         | 
| 231 | 
            +
                    # Now do another pass, prerendering stuff where necessary,
         | 
| 232 | 
            +
                    # extracting data, registering URLs to be exported, etc.
         | 
| 233 | 
            +
                    #
         | 
| 234 | 
            +
                    walk_tree do |node|
         | 
| 235 | 
            +
                      node.render_body! if node.should_prerender?
         | 
| 236 | 
            +
                      node.register_url! if node.should_publish?
         | 
| 261 237 | 
             
                    end
         | 
| 262 238 | 
             
                  end
         | 
| 263 | 
            -
                end
         | 
| 264 239 |  | 
| 265 | 
            -
             | 
| 266 | 
            -
             | 
| 267 | 
            -
             | 
| 240 | 
            +
                  def load_extension!
         | 
| 241 | 
            +
                    if extension = sibling("_node.rb")
         | 
| 242 | 
            +
                      instance_eval(extension.body)
         | 
| 243 | 
            +
                    end
         | 
| 244 | 
            +
                  end
         | 
| 268 245 |  | 
| 246 | 
            +
                  def should_prerender?
         | 
| 247 | 
            +
                    !folder? &&
         | 
| 248 | 
            +
                      (["json", "yml", "yaml", "rb", "toml"] & filters).any?
         | 
| 249 | 
            +
                  end
         | 
| 250 | 
            +
                end
         | 
| 269 251 |  | 
| 270 252 |  | 
| 253 | 
            +
                concerning :Rendering do
         | 
| 254 | 
            +
                  def view
         | 
| 255 | 
            +
                    @view ||= View.for(self)
         | 
| 256 | 
            +
                  end
         | 
| 271 257 |  | 
| 272 | 
            -
             | 
| 273 | 
            -
             | 
| 274 | 
            -
             | 
| 258 | 
            +
                  def render_body!
         | 
| 259 | 
            +
                    time = Benchmark.realtime do
         | 
| 260 | 
            +
                      Filters.apply!(self)
         | 
| 261 | 
            +
                    end
         | 
| 275 262 |  | 
| 276 | 
            -
             | 
| 277 | 
            -
                   | 
| 263 | 
            +
                    logger.info "Rendered #{url} in #{sprintf "%.1f", time * 1000}ms"
         | 
| 264 | 
            +
                  end
         | 
| 278 265 |  | 
| 279 | 
            -
                   | 
| 280 | 
            -
                     | 
| 281 | 
            -
             | 
| 282 | 
            -
                       | 
| 266 | 
            +
                  def body
         | 
| 267 | 
            +
                    if @body.nil?
         | 
| 268 | 
            +
                      data   # make sure data is lazy-loaded
         | 
| 269 | 
            +
                      render_body!
         | 
| 283 270 | 
             
                    end
         | 
| 284 271 |  | 
| 285 | 
            -
                     | 
| 286 | 
            -
             | 
| 287 | 
            -
             | 
| 272 | 
            +
                    @body
         | 
| 273 | 
            +
                  end
         | 
| 274 | 
            +
             | 
| 275 | 
            +
                  def render(opts = {})
         | 
| 276 | 
            +
                    layout = opts[:layout]
         | 
| 277 | 
            +
                    view.opts.merge!(opts)
         | 
| 278 | 
            +
                    (layout && apply_layout?) ? apply_layout(body) : body
         | 
| 279 | 
            +
                  end
         | 
| 280 | 
            +
             | 
| 281 | 
            +
                  def apply_layout(input)
         | 
| 282 | 
            +
                    walk_up(input) do |node, current|
         | 
| 283 | 
            +
                      if layout = node.sibling("_layout")
         | 
| 284 | 
            +
                        tilt = Flutterby::Filters.tilt(layout.ext, layout.source)
         | 
| 285 | 
            +
                        tilt.render(view) { current }.html_safe
         | 
| 286 | 
            +
                      else
         | 
| 287 | 
            +
                        current
         | 
| 288 | 
            +
                      end
         | 
| 288 289 | 
             
                    end
         | 
| 289 290 | 
             
                  end
         | 
| 290 | 
            -
                end
         | 
| 291 291 |  | 
| 292 | 
            -
             | 
| 293 | 
            -
             | 
| 292 | 
            +
                  def apply_layout?
         | 
| 293 | 
            +
                    page?
         | 
| 294 | 
            +
                  end
         | 
| 294 295 | 
             
                end
         | 
| 295 296 |  | 
| 296 | 
            -
                def read_yaml!
         | 
| 297 | 
            -
                  @data.merge!(YAML.load(body))
         | 
| 298 | 
            -
                end
         | 
| 299 297 |  | 
| 300 | 
            -
                def read_yml!
         | 
| 301 | 
            -
                  read_yaml!
         | 
| 302 | 
            -
                end
         | 
| 303 298 |  | 
| 304 | 
            -
                def read_toml!
         | 
| 305 | 
            -
                  @data.merge!(TOML.parse(body))
         | 
| 306 | 
            -
                end
         | 
| 307 299 |  | 
| 308 300 |  | 
| 309 301 | 
             
                #
         | 
    
        data/lib/flutterby/version.rb
    CHANGED
    
    
    
        data/lib/flutterby/view.rb
    CHANGED
    
    | @@ -35,6 +35,32 @@ module Flutterby | |
| 35 35 | 
             
                  node.siblings(*args)
         | 
| 36 36 | 
             
                end
         | 
| 37 37 |  | 
| 38 | 
            +
                def tag(name, attributes)
         | 
| 39 | 
            +
                  ActiveSupport::SafeBuffer.new.tap do |output|
         | 
| 40 | 
            +
                    attributes_str = attributes.keys.sort.map do |k|
         | 
| 41 | 
            +
                      %{#{h k}="#{h attributes[k]}"}
         | 
| 42 | 
            +
                    end.join(" ")
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                    opening_tag = "#{h name.downcase} #{attributes_str}".strip
         | 
| 45 | 
            +
                    output << "<#{opening_tag}>".html_safe
         | 
| 46 | 
            +
                    output << yield if block_given?
         | 
| 47 | 
            +
                    output << "</#{h name}>".html_safe
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                def link_to(text, target, attrs = {})
         | 
| 52 | 
            +
                  href = case target
         | 
| 53 | 
            +
                  when Flutterby::Node then target.url
         | 
| 54 | 
            +
                  else target.to_s
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  tag(:a, attrs.merge(href: href)) { text }
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                def debug(obj)
         | 
| 61 | 
            +
                  tag(:pre, class: "debug") { h obj.to_yaml }
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
             | 
| 38 64 | 
             
                class << self
         | 
| 39 65 | 
             
                  # Factory method that returns a newly created view for the given node.
         | 
| 40 66 | 
             
                  # It also makes sure all available _view.rb extensions are loaded.
         | 
    
        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.4.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-21 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bundler
         | 
| @@ -364,18 +364,18 @@ files: | |
| 364 364 | 
             
            - lib/flutterby/version.rb
         | 
| 365 365 | 
             
            - lib/flutterby/view.rb
         | 
| 366 366 | 
             
            - lib/templates/new_project/.gitignore
         | 
| 367 | 
            -
            - lib/templates/new_project/Gemfile
         | 
| 367 | 
            +
            - lib/templates/new_project/Gemfile.tt
         | 
| 368 368 | 
             
            - lib/templates/new_project/README.md
         | 
| 369 369 | 
             
            - lib/templates/new_project/bin/flutterby
         | 
| 370 370 | 
             
            - lib/templates/new_project/site/_config.toml
         | 
| 371 371 | 
             
            - lib/templates/new_project/site/_layout.slim
         | 
| 372 372 | 
             
            - lib/templates/new_project/site/_view.rb
         | 
| 373 373 | 
             
            - lib/templates/new_project/site/about.html.md
         | 
| 374 | 
            -
            - lib/templates/new_project/site/blog/2017-01-01-hello-world.html.md
         | 
| 375 374 | 
             
            - lib/templates/new_project/site/blog/_layout.slim
         | 
| 376 375 | 
             
            - lib/templates/new_project/site/blog/_list.html.slim
         | 
| 377 376 | 
             
            - lib/templates/new_project/site/blog/_node.rb
         | 
| 378 377 | 
             
            - lib/templates/new_project/site/blog/_view.rb
         | 
| 378 | 
            +
            - lib/templates/new_project/site/blog/hello-world.html.md.tt
         | 
| 379 379 | 
             
            - lib/templates/new_project/site/css/styles.css.scss
         | 
| 380 380 | 
             
            - lib/templates/new_project/site/index.html.slim
         | 
| 381 381 | 
             
            - lib/templates/new_project/site/js/app.js
         |