showcase-rails 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|

|
|
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
|