Skip to content

Introduce Core Component Generator #252

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions docs/contribute/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,29 @@ Feel free to take a look at other examples and copy their structure!
Note: We will not approve pull requests that introduce new concepts or components without documentation. Same goes for existing concepts & components.
If you change the behavior of an existing part of this project, make sure to also update the corresponding part of the documentation!

## Core Components

Core Components are an essential part of the `matestack-ui-core` gem.
If you are planning to contribute to Matestack you can start doing that by creating a core component. To help you getting started you can use the Core Component Generator.

The generator will create a matestack core component to `app/concepts/matestack/ui/core`.

Example:

```bash
rails generate matestack:core:component div
```

This will create a component for the HTML `<div>` tag and will generate the following files:

```bash
app/concepts/matestack/ui/core/div/div.haml
app/concepts/matestack/ui/core/div/div.rb
spec/usage/components/div_spec.rb
docs/components/div.md
```


## Tests

To assure this project is and remains in great condition, we heavily rely on automated tests. Tests are defined in `/spec` folder and can be executed by running:
Expand Down
16 changes: 16 additions & 0 deletions lib/generators/matestack/core/component/USAGE
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Description:
This generates a matestack core component in app/concepts/matestack, a spec file and a docs file.

Pass the name of the component under_scored.

Example 1:
`rails generate matestack:core:component NAME`

This will create:
app/concepts/matestack/ui/core/NAME/NAME.haml
app/concepts/matestack/ui/core/NAME/NAME.rb
spec/usage/components/NAME_spec.rb
docs/components/NAME.md

This will insert a link to the docs in:
docs/components/README.md
23 changes: 23 additions & 0 deletions lib/generators/matestack/core/component/component_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

module Matestack
module Core
module Generators
class ComponentGenerator < Rails::Generators::NamedBase
source_root File.expand_path('templates', __dir__)

def create_core_component
template 'app/concepts/matestack/ui/core/%file_name%/%file_name%.haml'
template 'app/concepts/matestack/ui/core/%file_name%/%file_name%.rb'
template 'spec/usage/components/%file_name%_spec.rb'
template 'docs/components/%file_name%.md'

inject_into_file 'docs/components/README.md', before: "\n## Dynamic Core Components\n" do <<~RUBY
- [#{file_name.underscore}](/docs/components/#{file_name.underscore}.md)
RUBY
end
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
%<%= file_name.underscore %>{@tag_attributes}
- if options[:text].blank? && block_given?
= yield
- else
= options[:text]
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Matestack::Ui::Core::<%= file_name.camelcase %>
class <%= file_name.camelcase %> < Matestack::Ui::Core::Component::Static
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# matestack core component: <%= file_name.camelcase %>

Show [specs](/spec/usage/components/<%= file_name.underscore %>_spec.rb)

The HTML `<<%= file_name.underscore %>>` tag implemented in ruby.

## Parameters

This component can take 2 optional configuration params and either yield content or display what gets passed to the `text` configuration param.

#### # id (optional)
Expects a string with all ids the `<<%= file_name.underscore %>>` should have.

#### # class (optional)
Expects a string with all classes the `<<%= file_name.underscore %>>` should have.

## Example 1: Yield a given block

```ruby
<%= file_name.underscore %> id: 'foo', class: 'bar' do
plain '<%= file_name.camelcase %> example 1' # optional content
end
```

returns

```html
<<%= file_name.underscore %> id="foo" class="bar">
<%= file_name.camelcase %> example 1
</<%= file_name.underscore %>>
```

## Example 2: Render `options[:text]` param

```ruby
<%= file_name.underscore %> id: 'foo', class: 'bar', text: '<%= file_name.camelcase %> example 2'
```

returns

```html
<<%= file_name.underscore %> id="foo" class="bar">
<%= file_name.camelcase %> example 2
</<%= file_name.underscore %>>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require_relative '../../support/utils'
include Utils

describe '<%= file_name.camelcase %> component', type: :feature, js: true do
it 'Renders a simple and enhanced <%= file_name.underscore %> tag on a page' do
class ExamplePage < Matestack::Ui::Page
def response
components {
# Simple <%= file_name.underscore %>
<%= file_name.underscore %> text: 'Simple <%= file_name.underscore %> tag'

# Enhanced <%= file_name.underscore %>
<%= file_name.underscore %> id: 'my-id', class: 'my-class' do
plain 'Enhanced <%= file_name.underscore %> tag'
end
}
end
end

visit '/example'

static_output = page.html

expected_static_output = <<~HTML
<<%= file_name.underscore %>>Simple <%= file_name.underscore %> tag</<%= file_name.underscore %>>
<<%= file_name.underscore %> id="my-id" class="my-class">Enhanced <%= file_name.underscore %> tag</<%= file_name.underscore %>>
HTML

expect(stripped(static_output)).to include(stripped(expected_static_output))
end
end
14 changes: 14 additions & 0 deletions spec/dummy/docs/components/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Core Components

matestack provides a wide set of core components, which enables you to easily build your UI.
You can build your [own components](/docs/extend/custom_components.md) as well, either static or dynamic.

## Static Core Components

- [br](/docs/components/br.md)
- [img](/docs/components/img.md)

## Dynamic Core Components

- [transition](/docs/components/transition.md)
- [onclick](/docs/components/onclick.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# frozen_string_literal: true

require 'generator_spec'
require 'generators/matestack/core/component/component_generator'

describe Matestack::Core::Generators::ComponentGenerator, type: :generator do
let(:dummy) { File.expand_path(File.join(__FILE__, '..', '..', '..', '..', '..', '..', 'dummy')) }
let(:dummy_copy) { File.expand_path(File.join(__FILE__, '..', '..', '..', '..', '..', '..', 'dummy_copy')) }

before :each do
FileUtils.cp_r dummy, dummy_copy
end

after :each do
FileUtils.rm_rf dummy
FileUtils.cp_r dummy_copy, dummy
FileUtils.rm_rf dummy_copy
end

destination Rails.root

it 'creates a core component' do
run_generator %w(div)

assert_file 'app/concepts/matestack/ui/core/div/div.rb', /module Matestack::Ui::Core::Div/
assert_file 'app/concepts/matestack/ui/core/div/div.rb', /class Div < Matestack::Ui::Core::Component::Static/

assert_file 'app/concepts/matestack/ui/core/div/div.haml', /%div{@tag_attributes}/

assert_file 'spec/usage/components/div_spec.rb', /describe 'Div component', type: :feature, js: true do/
assert_file 'spec/usage/components/div_spec.rb', /div text: 'Simple div tag'/
assert_file 'spec/usage/components/div_spec.rb', %r{<div>Simple div tag</div>}
assert_file 'spec/usage/components/div_spec.rb', /div id: 'my-id', class: 'my-class' do/
assert_file 'spec/usage/components/div_spec.rb', %r{<div id="my-id" class="my-class">Enhanced div tag</div>}

assert_file 'docs/components/div.md', /# matestack core component: Div/
assert_file 'docs/components/div.md', %r{Show \[specs\]\(/spec/usage/components/div_spec.rb\)}
assert_file 'docs/components/div.md', /The HTML `<div>` tag implemented in ruby./
assert_file 'docs/components/div.md', /Expects a string with all ids the `<div>` should have./
assert_file 'docs/components/div.md', /Expects a string with all classes the `<div>` should have./
assert_file 'docs/components/div.md', /div id: 'foo', class: 'bar' do/
assert_file 'docs/components/div.md', /div id: 'foo', class: 'bar', text: 'Div example 2'/
assert_file 'docs/components/div.md', /<div id="foo" class="bar">/

assert_file 'docs/components/README.md', %r{- \[div\]\(/docs/components/div.md\)}
end
end