tutorial-layout

Basics Learn about Layouts Renderer fun More about Dynasnips Cleaning up

Layouts

Since you almost certainly want your site to look good, one of the first things you’ll want to change in your vanilla site is the layout.

When the browser requests a snip, normally vanilla will present it within a layout template. This would typically include a header, a footer, and any other peripheral markup that shouldn’t be within the content of the snip itself. If you’re familiar with the construction of web applications, this will be exactly as you expect.

Layouts are just like any other snip - they can be sent through a renderer, and include other snips. The default layout snip is called, predictable, layout.snip, and here’s the content:

<!DOCTYPE html>
<html lang="en">
  <head>
    {head}
  </head>
  <body>
    <nav>
      {navigation}
    </nav>
    <article class="h-entry">
      <header>
        <span class="p-name">{title-for}</span>
        <p>{snip-details}</p>
      </header>
      <section class="e-content">
        {current_snip}
      </section>
    </article>
    <footer>
      {footer}
    </footer>
  </body>
</html>

When you request /start, this is the snip that’s actually rendered first. If this snip was just text, that’s all that would be returned; however, there are some dynasnip calls in here which help us actually return the content that the user requested.

current_snip

The most significant is the call to current_snip. This figures out what snip was actually requested (e.g. if the url is /start, it’s the start snip), and renders it in place.

Here’s the source of current_snip:

class CurrentSnip < Vanilla::Dynasnip
  usage %|
    The current_snip dyna normally returns the result of rendering the snip named by the
    'snip' value in the parameters. This way, it can be used in templates to place the currently
    requested snip, in its rendered form, within the page.

    It can also be used to determine an attribute of the current snip in a consistent way:

      {current_snip name}

    will output the name of the current snip.
  |

  def handle(attribute=nil)
    return usage if app.request.snip_name == snip_name

    if attribute ||= app.request.part
      %|{"#{app.request.snip_name}"."#{attribute}"}|
    else
      %|{"#{app.request.snip_name}"}|
    end
  end
  self
end

The default case just renders a string corresponding to snip inclusion of whichever snip was actually requested. In the case of /start, this will generate the string “

Most recently

Not all accusations are baseless

They don’t work anymore, those baseless accusations that anyone we disagree with is a racist, misogynist, fascist.

OK, so, DHH wrote this. The post, I assume (see later) largely written to say “look, I was right about DEI”, also pretty clearly suggests that applying those labels to Trump is “baseless”, and that the election demonstrated that people now see through a noisy minority throwing those accusations – at Trump in this case – for the overall good of everyone. The wisdom of the crowd has overcome political correctness, maybe.

Erk.

Previously

”, which Vanilla itself then deals with, including the contents of that snip using the right renderer and so on, placing our snip in the appropriate place in the layout.

Other dynas

Of course, you can put other plain content in your layout, and other dynasnips too. In the provided layout there are calls to three other dynasnips.

The first is page_title, which simply places a (hopefully) meaningful string in the title element of the page. Snips can set the title to be used by defining a :page_title attribute. As usual, the source explains it more clearly:

class PageTitle < Vanilla::Dynasnip
  def handle
    if app.request.snip
      app.request.snip.page_title || app.request.snip.title || app.request.snip.name
    else
      "Not found"
    end
  end

  self
end

The second is link_to, which is used to create links to other snips by name; although of course you can still just write HTML, this is often more convenient and wiki-esque. Here’s the source:

class LinkTo < Vanilla::Dynasnip
  usage %|
The link_to dyna lets you create links between snips: 

  {link_to blah} 

would insert a link to the blah snip.|

  def handle(name=nil, link_text=name, part=nil)
    return usage if requesting_this_snip?
    return "You must provide a snip name" unless name
    if app.soup[name]
      %{<a href="#{url_to(name, part)}">#{link_text}</a>}
    else
      %{<a class="missing" href="#{url_to(name, part)}">#{link_text}</a>}
    end
  end

  self
end

The third dynasnip used is link_to_current_snip, which returns an HTML link to the snip that’s currently being rendered. I’ll let you figure out how to view the source yourself.

Other layouts

Vanilla looks for a snip called layout by default, but this can be changed by setting the default_layout configuration option in your application, e.g.

class Application < Vanilla::App; end

Application.configure do |config|

  # other stuff..

  config.default_layout = "my_layout"
end

You can also override the layout on a per-snip basis, simply by setting the :layout attribute of the snip to the name of the layout snip to use instead.

Finally, if you implement a custom renderer class (see the renderers tutorial), you can also specify a layout to be used when the requested snip invokes that renderer. This can be useful if you have a particular kind of content that requires a different layout entirely.

Basics Learn about Layouts Renderer fun More about Dynasnips Cleaning up

interblah.net - tutorial

tutorial

; updated

Basics Learn about Layouts Renderer fun More about Dynasnips Cleaning up

Snips - the basic concept

Firstly, open the raw contents of this snip - either in your editor (search for vanilla-rb-tutorial.snip), or by opening this snip in raw format in a new window or tab. Ready? OK.

Every piece of information displayed here is stored as a snip. Snips, within their contents, can also reference other snips. When you request a snip, it will render into a page (or another kind of response), and also render any snips that it internally references.

For example, consider the snip tutorial-basic-snip-inclusion:

This is a snip, which includes another {link_to snip}: {tutorial-another-snip}

When this snip is rendered, it appears like this:

This is a snip, which includes another snip: this is another snip!

Notice the use of curly brackets to reference one snip from inside another. vanilla-rb finds these references to snips, then renders that snip and replaces it in the first snip. Neat!

Renderers

The way that a snip is rendered depends on whether or not it has an extension, or a render_as attribute set. For instance, the extention of this snip is

markdown

, and the render_as property of markdown_example is Markdown. Scroll to the bottom of the raw markdown_example snip in your editor, and you’ll see this being declared.

This means that the content of this snip will be passed through Vanilla::Renderers::Markdown before it is then rendered to the page. There are several different renders provided by Vanilla.rb at the moment:

You can see a lot of these renderers being exercised in the test snip.

It’s using this last renderer that a second concept of Vanilla is implemented - dynasnips.

Dynasnips

Because the curly braces simply cause a snip to be rendered, we can use this in conjunction with the Ruby renderer to run actual code. For instance, in the snip above:

This is a snip, which includes another {link_to snip}: {tutorial-another-snip}

we can see a reference to the link_to snip - snip.

Lets look at the raw content of link_to:

class LinkTo < Vanilla::Dynasnip
  usage %|
The link_to dyna lets you create links between snips: 

  {link_to blah} 

would insert a link to the blah snip.|

  def handle(name=nil, link_text=name, part=nil)
    return usage if requesting_this_snip?
    return "You must provide a snip name" unless name
    if app.soup[name]
      %{<a href="#{url_to(name, part)}">#{link_text}</a>}
    else
      %{<a class="missing" href="#{url_to(name, part)}">#{link_text}</a>}
    end
  end

  self
end

As you can see, it simply refers to the Ruby class LinkTo, which is contained within the vanilla-rb codebase. When the Ruby renderer is called, expects the given code to evaulate to a Ruby class. It then instantiates the class, and calls a handle method on the instance, passing it any other arguments from the snip inclusion. So, in the case of snip, the only argument is snip.

Included Dynasnips

Vanilla.rb includes a number of dynasnips by default. Here are a couple:

Anyway - that should be enough to get you started.

Basics Learn about Layouts Renderer fun More about Dynasnips Cleaning up