showcase-rails 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +25 -0
- data/app/assets/builds/showcase.css +1 -1
- data/app/models/showcase/path.rb +8 -16
- data/app/views/layouts/showcase.html.erb +2 -2
- data/lib/showcase/options.rb +89 -0
- data/lib/showcase/version.rb +1 -1
- data/lib/showcase.rb +33 -0
- metadata +4 -4
- data/app/models/showcase/options.rb +0 -51
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '081d707dee9578e786c17cb621826f685bf2a4f9eab5221037b2394ac3b6805b'
|
4
|
+
data.tar.gz: 46fad2bf9b84aba2bf22bf0a627eb225ee904cd67da55cda4c0690b34d8d5a07
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 480d2d5a3c891703603caec5131d3990e19d31c97e815c622d8c6152ec2c1519a430e55416fc63caab1d7f136dd0fe96bf9e45a39bbf854e39134339822f6157
|
7
|
+
data.tar.gz: d35a92bd276b05225cdb827a9d3ec832665e1b0978b2ec02294ecc3d0810fee926fbb5f58d989612177ebe879d833ea8a476057efa04ca845d5e3e2b1808694a
|
data/README.md
CHANGED
@@ -29,6 +29,31 @@ Which will then render the following:
|
|
29
29
|
|
30
30
|
![](/readme/example.png?raw=true "Showcase showing a button component")
|
31
31
|
|
32
|
+
## Using options contexts
|
33
|
+
|
34
|
+
Showcase also supports custom options contexts. They're useful for cases where the options have a very specific format and it would be nice to keep them standardized.
|
35
|
+
|
36
|
+
By default, Showcase ships Nice Partials and Stimulus contexts out of the box. Here's a sample of the Stimulus one:
|
37
|
+
|
38
|
+
```erb
|
39
|
+
<% showcase.options.stimulus controller: :welcome do |o| %>
|
40
|
+
<% o.optional.targets :greeter, "If the id of the target element must be printed" %>
|
41
|
+
<% end %>
|
42
|
+
```
|
43
|
+
|
44
|
+
In case Showcase didn't ship with a Stimulus context, here's how you could add it:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
# config/initializers/showcase.rb
|
48
|
+
if defined?(Showcase)
|
49
|
+
Showcase.options.define :stimulus do
|
50
|
+
def targets(name, ...)
|
51
|
+
option(%(data-#{@controller}-target="#{name}"), ...)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
32
57
|
## Automatic integration testing
|
33
58
|
|
34
59
|
Showcase automatically runs integration tests for all your Showcases by rendering them and asserting they respond with `200 OK`. As long as `gem "showcase-rails"` is in the `:test` group you're set.
|
data/app/models/showcase/path.rb
CHANGED
@@ -1,19 +1,16 @@
|
|
1
1
|
class Showcase::Path
|
2
|
-
class Tree < Struct.new(:id, :children)
|
2
|
+
class Tree < Struct.new(:id, :children, :root)
|
3
3
|
def initialize(id, children = [])
|
4
|
-
super
|
4
|
+
super(id, children, false)
|
5
5
|
end
|
6
|
+
alias_method :root?, :root
|
6
7
|
delegate :<<, to: :children
|
7
8
|
|
8
9
|
cached_partial_path = "showcase/engine/path/tree"
|
9
10
|
define_method(:to_partial_path) { cached_partial_path }
|
10
11
|
|
11
12
|
def name
|
12
|
-
|
13
|
-
end
|
14
|
-
|
15
|
-
def root?
|
16
|
-
id == "."
|
13
|
+
id == "." ? "Previews" : id
|
17
14
|
end
|
18
15
|
|
19
16
|
def ordered_children
|
@@ -24,15 +21,10 @@ class Showcase::Path
|
|
24
21
|
children.flat_map { _1.is_a?(Tree) ? _1.ordered_paths : _1 }
|
25
22
|
end
|
26
23
|
|
27
|
-
def self.index(
|
28
|
-
new(:discardable_root)
|
29
|
-
|
30
|
-
|
31
|
-
def index(paths)
|
32
|
-
paths.each do |path|
|
33
|
-
ids = yield path
|
34
|
-
ids.inject(self, :edge_for) << path
|
35
|
-
end
|
24
|
+
def self.index(paths)
|
25
|
+
paths.each_with_object new(:discardable_root) do |path, root|
|
26
|
+
yield(path).reduce(root, :edge_for) << path
|
27
|
+
end.children.sort_by(&:id).each { _1.root = true }
|
36
28
|
end
|
37
29
|
|
38
30
|
def edge_for(id)
|
@@ -4,8 +4,8 @@
|
|
4
4
|
<title>Showcase</title>
|
5
5
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6
6
|
|
7
|
-
<%= render "stylesheets" %>
|
8
|
-
<%= render "javascripts" %>
|
7
|
+
<%= render "showcase/engine/stylesheets" %>
|
8
|
+
<%= render "showcase/engine/javascripts" %>
|
9
9
|
</head>
|
10
10
|
|
11
11
|
<body>
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require "active_support/option_merger"
|
2
|
+
|
3
|
+
class Showcase::Options
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
def initialize(view_context)
|
7
|
+
@view_context = view_context
|
8
|
+
@options = []
|
9
|
+
@order = [:name, :required, :type, :default, :description]
|
10
|
+
end
|
11
|
+
delegate :empty?, to: :@options
|
12
|
+
|
13
|
+
# Showcase.options.define :stimulus do
|
14
|
+
# def value(name, ...)
|
15
|
+
# option("data-#{@controller}-#{name}-value", ...)
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
singleton_class.attr_reader :contexts
|
19
|
+
@contexts = Hash.new { |h,k| h[k] = Class.new Context }
|
20
|
+
|
21
|
+
def self.define(key, &block)
|
22
|
+
contexts[key].class_eval(&block) # Lets users reopen an already defined context class.
|
23
|
+
end
|
24
|
+
|
25
|
+
# showcase.options.stimulus controller: :welcome do |o|
|
26
|
+
# o.value :greeting, default: "Hello"
|
27
|
+
# end
|
28
|
+
def context(key, **options, &block)
|
29
|
+
context = self.class.contexts.fetch(key)
|
30
|
+
context.new(@view_context, @options, **options).tap { yield _1 if block_given? }
|
31
|
+
end
|
32
|
+
|
33
|
+
def required(*arguments, **keywords, &block)
|
34
|
+
if arguments.none?
|
35
|
+
ActiveSupport::OptionMerger.new(self, required: true)
|
36
|
+
else
|
37
|
+
option(*arguments, **keywords, required: true, &block)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def optional(*arguments, **keywords, &block)
|
42
|
+
if arguments.none?
|
43
|
+
ActiveSupport::OptionMerger.new(self, required: false)
|
44
|
+
else
|
45
|
+
option(*arguments, **keywords, required: false, &block)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
DEFAULT_OMITTED = Object.new
|
50
|
+
|
51
|
+
def option(name, description = nil, required: false, type: nil, default: DEFAULT_OMITTED, **options, &block)
|
52
|
+
description ||= @view_context.capture(&block).remove(/^\s+/).html_safe if block
|
53
|
+
|
54
|
+
type ||= type_from_default(default)
|
55
|
+
default = default == DEFAULT_OMITTED ? nil : default.inspect
|
56
|
+
|
57
|
+
@options << options.with_defaults(name: name, default: default, type: type, description: description, required: required)
|
58
|
+
end
|
59
|
+
|
60
|
+
def headers
|
61
|
+
@headers ||= @order | @options.flat_map(&:keys).uniq.sort
|
62
|
+
end
|
63
|
+
|
64
|
+
def each(&block)
|
65
|
+
@options.each do |option|
|
66
|
+
yield headers.index_with { option[_1] }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
class Context < Showcase::Options
|
73
|
+
def initialize(view_context, options, **kwargs)
|
74
|
+
super(view_context)
|
75
|
+
@options = options
|
76
|
+
kwargs.each { instance_variable_set(:"@#{_1}", _2) }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def type_from_default(default)
|
81
|
+
case default
|
82
|
+
when DEFAULT_OMITTED then String
|
83
|
+
when true, false then "Boolean"
|
84
|
+
when nil then "nil"
|
85
|
+
else
|
86
|
+
default.class
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/lib/showcase/version.rb
CHANGED
data/lib/showcase.rb
CHANGED
@@ -3,6 +3,7 @@ require_relative "showcase/version"
|
|
3
3
|
module Showcase
|
4
4
|
autoload :IntegrationTest, "showcase/integration_test"
|
5
5
|
autoload :RouteHelper, "showcase/route_helper"
|
6
|
+
autoload :Options, "showcase/options"
|
6
7
|
|
7
8
|
singleton_class.attr_accessor :sample_renderer
|
8
9
|
@sample_renderer = ->(lines) { tag.pre lines.join.strip_heredoc }
|
@@ -15,6 +16,38 @@ module Showcase
|
|
15
16
|
Dir.glob("**/*.*", base: File.join(root, previews_path))
|
16
17
|
end.uniq
|
17
18
|
end
|
19
|
+
|
20
|
+
def self.options
|
21
|
+
Options
|
22
|
+
end
|
23
|
+
|
24
|
+
options.define :stimulus do
|
25
|
+
def targets(name, ...)
|
26
|
+
option(%(data-#{@controller}-target="#{name}"), ...)
|
27
|
+
end
|
28
|
+
|
29
|
+
def values(name, ...)
|
30
|
+
option("data-#{@controller}-#{name}-value", ...)
|
31
|
+
end
|
32
|
+
|
33
|
+
def classes(name, ...)
|
34
|
+
option("data-#{@controller}-#{name}-class", ...)
|
35
|
+
end
|
36
|
+
|
37
|
+
def outlet(name, ...)
|
38
|
+
option("data-#{@controller}-#{name}-outlet", ...)
|
39
|
+
end
|
40
|
+
|
41
|
+
def action(name, ...)
|
42
|
+
option(%(data-action="#{name}"), ...)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
options.define :nice_partials do
|
47
|
+
def content_block(*arguments, **options, &block)
|
48
|
+
option(*arguments, **options, type: "Content Block", &block)
|
49
|
+
end
|
50
|
+
end
|
18
51
|
end
|
19
52
|
|
20
53
|
require "showcase/engine" if defined?(Rails::Engine)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: showcase-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Pence
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-02-
|
12
|
+
date: 2023-02-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -54,7 +54,6 @@ files:
|
|
54
54
|
- app/assets/javascripts/showcase.js
|
55
55
|
- app/controllers/showcase/engine_controller.rb
|
56
56
|
- app/controllers/showcase/previews_controller.rb
|
57
|
-
- app/models/showcase/options.rb
|
58
57
|
- app/models/showcase/path.rb
|
59
58
|
- app/models/showcase/preview.rb
|
60
59
|
- app/models/showcase/sample.rb
|
@@ -75,6 +74,7 @@ files:
|
|
75
74
|
- lib/showcase.rb
|
76
75
|
- lib/showcase/engine.rb
|
77
76
|
- lib/showcase/integration_test.rb
|
77
|
+
- lib/showcase/options.rb
|
78
78
|
- lib/showcase/route_helper.rb
|
79
79
|
- lib/showcase/version.rb
|
80
80
|
- lib/tasks/showcase_tasks.rake
|
@@ -100,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
100
|
- !ruby/object:Gem::Version
|
101
101
|
version: '0'
|
102
102
|
requirements: []
|
103
|
-
rubygems_version: 3.4.
|
103
|
+
rubygems_version: 3.4.7
|
104
104
|
signing_key:
|
105
105
|
specification_version: 4
|
106
106
|
summary: Showcase helps you show off and document your partials, components, view
|
@@ -1,51 +0,0 @@
|
|
1
|
-
class Showcase::Options
|
2
|
-
include Enumerable
|
3
|
-
|
4
|
-
def initialize(view_context)
|
5
|
-
@view_context = view_context
|
6
|
-
@options = []
|
7
|
-
@order = [:name, :required, :type, :default, :description]
|
8
|
-
end
|
9
|
-
delegate :empty?, to: :@options
|
10
|
-
|
11
|
-
def required(*arguments, **keywords, &block)
|
12
|
-
option(*arguments, **keywords, required: true, &block)
|
13
|
-
end
|
14
|
-
|
15
|
-
def optional(*arguments, **keywords, &block)
|
16
|
-
option(*arguments, **keywords, required: false, &block)
|
17
|
-
end
|
18
|
-
|
19
|
-
DEFAULT_OMITTED = Object.new
|
20
|
-
|
21
|
-
def option(name, description = nil, required: false, type: nil, default: DEFAULT_OMITTED, **options, &block)
|
22
|
-
description ||= @view_context.capture(&block).remove(/^\s+/).html_safe if block
|
23
|
-
|
24
|
-
type ||= type_from_default(default)
|
25
|
-
default = default == DEFAULT_OMITTED ? nil : default.inspect
|
26
|
-
|
27
|
-
@options << options.with_defaults(name: name, default: default, type: type, description: description, required: required)
|
28
|
-
end
|
29
|
-
|
30
|
-
def headers
|
31
|
-
@headers ||= @order | @options.flat_map(&:keys).uniq.sort
|
32
|
-
end
|
33
|
-
|
34
|
-
def each(&block)
|
35
|
-
@options.each do |option|
|
36
|
-
yield headers.index_with { option[_1] }
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
def type_from_default(default)
|
43
|
-
case default
|
44
|
-
when DEFAULT_OMITTED then String
|
45
|
-
when true, false then "Boolean"
|
46
|
-
when nil then "nil"
|
47
|
-
else
|
48
|
-
default.class
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|