├── .gitignore
├── .travis.yml
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── docs
├── creating-a-component.md
└── introduction.md
├── examples
├── block_component.rb
└── tag_component.rb
├── jekyll-spark.gemspec
├── lib
├── jekyll-spark.rb
└── jekyll
│ ├── spark.rb
│ └── spark
│ ├── base.rb
│ ├── block.rb
│ ├── tag.rb
│ └── version.rb
└── test
├── helper.rb
├── source
├── _config.yml
├── _plugins
│ ├── components
│ │ ├── blocks
│ │ │ ├── container.rb
│ │ │ ├── nested.rb
│ │ │ └── wistia_popover.rb
│ │ └── tags
│ │ │ ├── image.rb
│ │ │ └── wistia.rb
│ └── jekyll-spark.rb
├── _posts
│ └── 2016-01-01-base.md
└── components
│ ├── container.md
│ ├── image-markdown.md
│ ├── image.html
│ ├── test-nested.md
│ ├── wistia-markdown.md
│ ├── wistia-popover.md
│ └── wistia.html
├── test_component_container.rb
├── test_component_image.rb
├── test_component_props.rb
├── test_component_test_nested.rb
├── test_component_wistia.rb
├── test_component_wistia_popover.rb
└── test_unit_spark_base.rb
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /.bundle/
3 | /.yardoc
4 | /Gemfile.lock
5 | /_yardoc/
6 | /coverage/
7 | /doc/
8 | /pkg/
9 | /spec/reports/
10 | /tmp/
11 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: ruby
3 | rvm:
4 | - 2.3.3
5 | before_install: gem install bundler -v 1.13.7
6 |
7 | install:
8 | - bundle install
9 |
10 | script:
11 | - bundle exec rake test
12 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gem 'coveralls', require: false
4 | gem 'simplecov', require: false
5 |
6 | gemspec
7 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017 Help Scout
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Spark ✨ [](https://travis-ci.org/helpscout/jekyll-spark) [](https://badge.fury.io/rb/jekyll-spark) [](https://coveralls.io/github/helpscout/jekyll-spark?branch=master)
2 |
3 | A Jekyll library for building fast component-based UI.
4 |
5 | This library was heavily inspired by view/component creation from modern Javascript libraries like [React](https://facebook.github.io/react/) and [Vue](https://vuejs.org/).
6 |
7 | **Table of Contents**
8 |
9 | - [Install](#install)
10 | - [Documentation](#documenation)
11 | - [Examples](#examples)
12 |
13 | ## Install
14 |
15 | Add this line to your application's Gemfile:
16 |
17 | ```ruby
18 | gem 'jekyll-spark'
19 | ```
20 |
21 | And then execute:
22 | ```
23 | bundle
24 | ```
25 |
26 | Or install it yourself as:
27 | ```
28 | gem install jekyll-spark
29 | ```
30 |
31 |
32 |
33 | ## Documentation
34 |
35 | **[View the docs](https://github.com/helpscout/jekyll-spark/blob/master/docs/introduction.md)** to get started with Jekyll Components!
36 |
37 |
38 | ## Examples
39 |
40 | **[View the starter](https://github.com/helpscout/jekyll-spark/tree/master/examples)** Component view files.
41 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require 'bundler/gem_tasks'
2 | require 'rubygems'
3 | require 'rake'
4 | require 'rdoc'
5 | require 'date'
6 | require 'yaml'
7 | require 'rake/testtask'
8 |
9 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), *%w[lib]))
10 | require 'jekyll/version'
11 |
12 | Rake::TestTask.new(:test) do |test|
13 | test.libs << 'lib' << 'test'
14 | test.pattern = 'test/**/test_*.rb'
15 | test.verbose = true
16 | end
17 |
--------------------------------------------------------------------------------
/docs/creating-a-component.md:
--------------------------------------------------------------------------------
1 | # Creating a component
2 |
3 | Let's create our first component under `_plugins/tags`.
4 |
5 | We'll call it `napolean.rb`! Below is the [starting template](https://github.com/helpscout/jekyll-spark/tree/master/examples) of any Jekyll Component:
6 |
7 | ```ruby
8 | require "jekyll-spark"
9 |
10 | module Jekyll
11 | # Create your component class
12 | class NapoleanComponent < ComponentTag
13 | def template(context)
14 | render = %Q[
15 | # Put markup here!
16 | ]
17 | end
18 | end
19 | end
20 |
21 | # Register your component with Liquid
22 | Liquid::Template.register_tag(
23 | "Napolean", # Namespace your component
24 | Jekyll::NapoleanComponent, # Pass your newly created component class
25 | )
26 | ```
27 |
28 | ### Rendering markup
29 |
30 | Let's make this component render this GIF:
31 |
32 | 
33 |
34 |
35 | ```ruby
36 | require "jekyll-spark"
37 |
38 | module Jekyll
39 | class NapoleanComponent < ComponentTag
40 | def template(context)
41 | render = %Q[
42 |
43 |
44 |
45 | ]
46 | end
47 | end
48 | end
49 |
50 | Liquid::Template.register_tag(
51 | "Napolean",
52 | Jekyll::NapoleanComponent,
53 | )
54 | ```
55 |
56 | To use our tag component, all we have to do is use `{% Napolean %}` in our Jekyll `.html` or `.md` file:
57 |
58 | ```html
59 | Check out this component!
60 | {% Napolean %}
61 | ```
62 |
63 | That's it!
64 |
65 |
66 | ### Adding props
67 |
68 | "Props" are data that we can pass to our component.
69 |
70 | For our example, let's provide the ability to adjust the width of our image as well as provide a caption:
71 |
72 | ```html
73 | {% Napolean
74 | width: "300"
75 | caption: "Way to eat all the friggen chips Kip!"
76 | %}
77 | ```
78 |
79 | You can totally write everything in a single line (below). However, we recommend the above approach as it makes it much easier to add/remove/edit props.
80 |
81 | ```html
82 | {% Napolean width: "300" caption: "Way to eat all the friggen chips Kip!" %}
83 | ```
84 |
85 | In order to use our new `width` and `caption` props, we have to update our `template` method in our Napolean component. Prop data being passed to our component will be available in a `@prop` instance variable in our `.rb` file:
86 |
87 | ```ruby
88 | require "jekyll-spark"
89 |
90 | module Jekyll
91 | class NapoleanComponent < ComponentTag
92 | def template(context)
93 | # Declare props as variables
94 | # Not necessary, but highly recommended
95 | caption = @props["caption"]
96 | width = @props["width"]
97 |
98 | render = %Q[
99 |
100 |
101 | #{caption}
102 |
103 | ]
104 | end
105 | end
106 | end
107 |
108 | Liquid::Template.register_tag(
109 | "Napolean",
110 | Jekyll::NapoleanComponent,
111 | )
112 | ```
113 |
114 | The resulting compiled markup will be:
115 |
116 | ```html
117 |
118 |
119 | Way to eat all the friggen chips Kip!
120 |
121 | ```
122 |
123 |
124 | ### Syntax
125 |
126 | Below is a comparison between some syntax differences between Jekyll Components (Ruby) and React (ES6 Javascript):
127 |
128 | | Ruby | Javascript (React) | Description |
129 | | --- | --- | --- |
130 | | `@props["key"]` | `this.props.key` | Component prop data. |
131 | | `render =` | `render() { return ... } ` | Outputting the component's markup. |
132 | | `%Q[ ... ]` | `` `...` `` | String interpolation wrapper. |
133 | | `#{var}` | `${var} ` | String interpolated variable. |
134 |
135 |
136 |
137 | ## Creating a block component
138 |
139 | Let's say we want to update our component to be a block instead. It'll make it more intuitive to add caption. Maybe something like:
140 |
141 | ```html
142 | {% Napolean width: "300" %}
143 | This tastes like the cow got into an onion patch.
144 | {% endNapolean %}
145 | ```
146 |
147 | It's pretty easy! The only thing we need to change in our `napolean.rb` file is the Class our component inherits from.
148 |
149 | Before:
150 | ```ruby
151 | class NapoleanComponent < ComponentTag
152 | ```
153 |
154 | After:
155 | ```ruby
156 | class NapoleanComponent < ComponentBlock
157 | ```
158 |
159 |
160 | ### That's it!
161 |
162 | You've got the basics to create some awesome components in Jekyll.
163 |
164 | 
165 |
--------------------------------------------------------------------------------
/docs/introduction.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | Components are `.rb` files that are added to your Jekyll project's default `_plugins/` directory:
4 |
5 | ```shell
6 | my-jekyll/
7 | └── _plugins/
8 | └── *Add components here*
9 | ```
10 |
11 | There are two types are Components:
12 |
13 | **Tags**
14 |
15 | These components are created using Liquid [Tags](http://www.rubydoc.info/github/Shopify/liquid/Liquid/Tag), and they do not contain content when used.
16 |
17 | Example:
18 | ```html
19 | {% Napolean id: "skillz" class: "nunchucks bow staff computer-hacking" %}
20 | ```
21 |
22 | **Blocks**
23 |
24 | These components are created using Liquid [Blocks](http://www.rubydoc.info/github/Shopify/liquid/Liquid/Block), and they **do** contain content when used.
25 |
26 | Example:
27 | ```html
28 | {% Napolean class: "chapstick" %}
29 | But my lips hurt real bad!
30 | {% endNapolean %}
31 | ```
32 |
33 | Because of these types, we recommend you organize your components in your `_plugins/` directory into `tags` and `blocks` directories:
34 |
35 | ```shell
36 | my-jekyll/
37 | └── _plugins/
38 | ├── blocks/
39 | └── tags/
40 | ```
41 |
42 |
43 | ### Up next
44 |
45 | Learn how to [create a component](creating-a-component.md).
46 |
--------------------------------------------------------------------------------
/examples/block_component.rb:
--------------------------------------------------------------------------------
1 | require "jekyll-spark"
2 |
3 | module Jekyll
4 | class ExampleBlockComponent < ComponentBlock
5 | def template(context)
6 | # Declare props as variables here
7 | content = @props["content"]
8 |
9 | # Output rendered markup
10 | render = %Q[
11 |