Skip to content

Commit

Permalink
More content
Browse files Browse the repository at this point in the history
  • Loading branch information
joeldrapper committed Sep 3, 2024
1 parent a037510 commit b24b80b
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 46 deletions.
42 changes: 5 additions & 37 deletions .vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -11,46 +11,14 @@ export default defineConfig({
],
sidebar: [
{
text: "Getting Started",
text: "Guide",
items: [
{ text: "Intro", link: "/guide/" },
{ text: "Setup", link: "/guide/setup" }
]
},
{
text: "Rails",
items: [
{ text: "Views", link: "/guide/rails/views" },
{ text: "Generators" },
{ text: "Migrating to Phlex" },
],
},
{
text: "HTML",
collapsed: false,
items: [
{ text: "Introduction" },
{ text: "Elements" },
{ text: "Attributes" },
{ text: "Comments" },
{ text: "Helpers" },
{ text: "Whitespace" },
{ text: "Setup", link: "/guide/setup" },
{ text: "Your first component", link: "/guide/first-component" },
{ text: "Under the hood", link: "/guide/under-the-hood" },
],
},
{
text: "SVG",
collapsed: false,
items: [
{ text: "Introduction" },
{ text: "Elements" },
{ text: "Attributes" },
],
},
{
text: "CSV",
collapsed: false,
items: [{ text: "Introduction" }, { text: "CSV Injection" }],
},
],

socialLinks: [
Expand All @@ -61,4 +29,4 @@ export default defineConfig({
message: "Released under the MIT License.",
},
},
})
});
1 change: 1 addition & 0 deletions guide/first-component.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Building your first component in Phlex
20 changes: 11 additions & 9 deletions guide/setup.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
# Setup
# Up and running 🏃‍➡️

## Setting up Phlex with Rails
Before we get too far, let’s get Phlex up and running in your app.

Let’s be honest, most of us are going to be using this with Rails so we’ll start there.
Phlex is a standalone Ruby library with zero dependencies, but most folks will want to use it with [Ruby on Rails](https://rubyonrails.org) so let’s start there for the sake of this guide.

First, add `phlex-rails` to your Gemfile. The quickest way to do this is to run:
It’s possible to use Phlex with [Sinatra](https://sinatrarb.com), [Roda](https://github.com/jeremyevans/roda), [Hanami](https://hanamirb.org), and any other Ruby web framework, but you’ll need to kick off the rendering yourself.

## Installing Phlex in a Rails app

To install Phlex in a Rails app, you’ll need to add the `phlex-rails` gem to your `Gemfile`. The `phlex-rails` gem includes the `phlex` gem as a dependency, so you won’t need to add that separately. `phlex-rails` also includes a generator to help you get started.

Start by running:

```
bundle add phlex-rails
```

This will add the latest version of `phlex` and `phlex-rails` and run `bundle install` for you. Now that the gem is installed, you’ll want to run the install geneartor:
This will install the latest version of `phlex` and `phlex-rails` and add `phlex-rails` to your `Gemfile`. Once that’s finished, you’ll want to run the install geneartor to kick things off:

```
bundle exec rails generate phlex:install
```

## Setting up Phlex without Rails

Phlex is actually a standalone library with zero dependencies. You can use it in any Ruby project, but you’ll need to kick off the rendering yourself.
89 changes: 89 additions & 0 deletions guide/under-the-hood.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Under the hood

You’ve successfully installed Phlex and rendered your first component. Now let’s take a moment to understand what’s happening behind the scenes. To do this, we’re going to build a mineature version of Phlex from scratch.

It won’t have advanced features, performance optimizations or HTML safety, but I think it’ll give you a good sense of things.

## Buffers and hirearchy

We’ll start by creating a `Component` class with a `@buffer` instance variable. Phlex uses a mutible String for its buffer, but we’ll use an Array since it’s easier to debug.

```ruby
class Component
def initialize
@buffer = []
end
end
```

Now we want to be able to render HTML tags. Let’s start with `<div>` and we can add a few more later.

```ruby
def div
@buffer << "<div>"
yield(self) if block_given?
@buffer << "</div>"
end
```

Our `div` method first pushes an opening `<div>` tag onto the buffer, then yields itself to the block if a block is given. Finally, it pushes a closing `</div>` tag onto the buffer.

Let’s add one more method so we can render our components to a string.

```ruby
def call
view_template
@buffer.join
end
```

This method, `call`, first calls the `view_template` method (which we haven’t defined yet) then it joins the buffer into a single string and returns it.

The whole class should look like this:

```ruby
class Component
def initialize
@buffer = []
end

def call
view_template
@buffer.join
end

def div
@buffer << "<div>"
yield if block_given?
@buffer << "</div>"
end
end
```

Now we’re ready to create a component. Let’s make a simple `HelloWorld` component — though we’re not quite ready to say `"Hello World"` just yet. Instead, we’ll render a couple of nested divs.

```ruby
class HelloWorld < Component
def view_template
div {
div
}
end
end
```

This `HelloWorld` component inherits from our abstract `Component` class and implements the `view_template` method that we called from the `call` method before.

Let’s see what it looks like when we `call` our `HelloWorld` component to render it:

```ruby
puts HelloWorld.new.call
```

You should see the following output with one div nested inside another:

```html
<div><div></div></div>
```

Ruby handled the hierarchy for us. We got part way into the first div when we _yielded_ to the block which started a new div. Since there was no block given to this inner div, it closed immediately yielding control back to the original outer div, which then closed.

0 comments on commit b24b80b

Please sign in to comment.