showcase-rails 0.2.2 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 24a9dbd46ccbe35d34075383efeb99bedb2825c56976b7b5ce2bb5fba294ffcc
4
- data.tar.gz: 28dc05bf705b386845aa630a188d87295ba6069445583af781478e10052d5ae8
3
+ metadata.gz: aead2040b7c095f85df0c152c6d96aa3bec927e52f49db09f407926536ce36ae
4
+ data.tar.gz: c5fd847fd56d1ffa39a4d9aae681106685c71aef2e199bbb637158ec80f43cbc
5
5
  SHA512:
6
- metadata.gz: e62b4977a6c7f8cb53fe74373e17de88870cf245ddcb449be791afb5cab22197a03aabe263aa543bde5d86bbd683e8914002ba133178825542abfe455bdbbda9
7
- data.tar.gz: 77213dbf5e976b366ec64947b0e0a0efcf50eb8b0360a7d6698e72ea452512c5d8a37f91e838c9546a98c5b6f3d6b54cca4215bb8f301ad80e31029103de068c
6
+ metadata.gz: 3ffe05a31b2be808620a735573c1cbaf705cceb75bdf03f750193f0ad5534096cb3bc81a4d98e51b80712408ca7b3b60465e85a23828ae469da9af3fdb348db5
7
+ data.tar.gz: f6ec194dec60349be7b4effd48a20517c8af04e45604b104687a6479a4bba92087ae11b36d702fac03e8d1faebb22521b6d49e62d816b5a42d187e027ce9ce00
data/README.md CHANGED
@@ -29,11 +29,59 @@ Which will then render the following:
29
29
 
30
30
  ![](/readme/example.png?raw=true "Showcase showing a button component")
31
31
 
32
- ## Automatic integration testing
32
+ ## Using options contexts
33
33
 
34
- 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.
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
35
 
36
- If you want to tweak this, run `bin/rails showcase:install:integration_test` and open `test/integration/showcase_test.rb`. You can then add your own `setup` and `teardown` hooks, as well as override the provided `assert_showcase_preview` to add custom assertions.
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
+
57
+ ## Automatic previews testing
58
+
59
+ Showcase automatically runs tests for all your Showcases by rendering them. As long as `gem "showcase-rails"` is in the `:test` group you're set.
60
+
61
+ If you want to tweak this, run `bin/rails showcase:install:previews_test` and open `test/views/showcase_test.rb`. You can then add your own `setup` and `teardown` hooks, as well as override the provided `assert_showcase_preview` to add custom assertions.
62
+
63
+ If you need custom assertions for specific previews and their samples, you can use the `test` helper:
64
+
65
+ ```ruby
66
+ # test/views/showcase_test.rb
67
+ require "test_helper"
68
+
69
+ class ShowcaseTest < Showcase::PreviewsTest
70
+ test showcase: "combobox" do
71
+ # This test block runs within the #combobox container element.
72
+ assert_text "This is a combobox, for sure."
73
+ end
74
+
75
+ test showcase: "button", id: "basic" do
76
+ # This test block runs within the #button container element's #basic sample.
77
+ assert_button class: ["text-xs"]
78
+ end
79
+
80
+ test "some non-Showcase test" do
81
+ # You can still use the regular Rails `test` method too.
82
+ end
83
+ end
84
+ ```
37
85
 
38
86
  ## View examples
39
87
 
@@ -70,7 +118,7 @@ copy the file from our repo `app/views` directory into your `app/views` director
70
118
 
71
119
  ### Loading your own assets
72
120
 
73
- Showcase bundles its own `showcase.js` and `showcase.css` asset files through
121
+ Showcase bundles its own `showcase.js`, `showcase.css` and `showcase.highlights.css` asset files through
74
122
  Action View's [javascript_include_tag][] and [stylesheet_link_tag][].
75
123
 
76
124
  If your assets require more sophisticated loading techniques, declare your own
@@ -78,12 +126,24 @@ versions of the [showcase/engine/_javascripts.html.erb][] and
78
126
  [showcase/engine/_stylesheets.html.erb][] partials. When customizing those
79
127
  partials, make sure to include `"showcase"` in your list of assets.
80
128
 
81
-
82
129
  [javascript_include_tag]: https://edgeapi.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html#method-i-javascript_include_tag
83
130
  [stylesheet_link_tag]: https://edgeapi.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html#method-i-stylesheet_link_tag
84
131
  [showcase/engine/_javascripts.html.erb]: ./showcase/engine/_javascripts.html.erb
85
132
  [showcase/engine/_stylesheets.html.erb]: ./showcase/engine/_stylesheets.html.erb
86
133
 
134
+ #### Loading your own syntax highlighting theme
135
+
136
+ By default, Showcase's syntax highlighting runs on Rouge's "github" theme.
137
+
138
+ To use a different theme, override [showcase/engine/_stylesheets.html.erb][] with the following, replacing `:magritte` with a [valid theme](rouge-themes):
139
+
140
+ ```erb
141
+ <%= stylesheet_link_tag "application", "showcase" %> # We've removed the default showcase.highlights file here.
142
+ <%= tag.style Rouge::Theme.find(:magritte).render(scope: ".sc-highlight") %>
143
+ ```
144
+
145
+ [rouge-themes]: https://github.com/rouge-ruby/rouge/tree/master/lib/rouge/themes
146
+
87
147
  ## Installation
88
148
 
89
149
  Add this line to your application's Gemfile. To get the automatic integration testing make sure the `showcase-rails` gem is available to your test environment:
@@ -104,6 +164,12 @@ Or install it yourself as:
104
164
  $ gem install showcase-rails
105
165
  ```
106
166
 
167
+ Then add the following in your `config/routes.rb` within the block passed to `Rails.application.routes.draw`:
168
+
169
+ ```ruby
170
+ mount Showcase::Engine, at: "/docs/showcase" if defined?(Showcase::Engine)
171
+ ```
172
+
107
173
  ## Contributing
108
174
  Contribution directions go here.
109
175
 
@@ -1,5 +1,5 @@
1
1
  /*
2
- ! tailwindcss v3.2.6 | MIT License | https://tailwindcss.com
2
+ ! tailwindcss v3.2.7 | MIT License | https://tailwindcss.com
3
3
  */
4
4
 
5
5
  /*
@@ -985,6 +985,14 @@ select {
985
985
  background-color: rgb(238 242 255 / var(--tw-bg-opacity));
986
986
  }
987
987
 
988
+ .hover\:sc-text-inherit:hover {
989
+ color: inherit;
990
+ }
991
+
992
+ .hover\:sc-no-underline:hover {
993
+ text-decoration-line: none;
994
+ }
995
+
988
996
  @media (min-width: 768px) {
989
997
  .md\:sc-text-lg {
990
998
  font-size: 1.125rem;
@@ -0,0 +1,112 @@
1
+ .sc-highlight table td { padding: 5px; }
2
+ .sc-highlight table pre { margin: 0; }
3
+ .sc-highlight, .sc-highlight .w {
4
+ color: #24292f;
5
+ background-color: #f6f8fa;
6
+ }
7
+ .sc-highlight .k, .sc-highlight .kd, .sc-highlight .kn, .sc-highlight .kp, .sc-highlight .kr, .sc-highlight .kt, .sc-highlight .kv {
8
+ color: #cf222e;
9
+ }
10
+ .sc-highlight .gr {
11
+ color: #f6f8fa;
12
+ }
13
+ .sc-highlight .gd {
14
+ color: #82071e;
15
+ background-color: #ffebe9;
16
+ }
17
+ .sc-highlight .nb {
18
+ color: #953800;
19
+ }
20
+ .sc-highlight .nc {
21
+ color: #953800;
22
+ }
23
+ .sc-highlight .no {
24
+ color: #953800;
25
+ }
26
+ .sc-highlight .nn {
27
+ color: #953800;
28
+ }
29
+ .sc-highlight .sr {
30
+ color: #116329;
31
+ }
32
+ .sc-highlight .na {
33
+ color: #116329;
34
+ }
35
+ .sc-highlight .nt {
36
+ color: #116329;
37
+ }
38
+ .sc-highlight .gi {
39
+ color: #116329;
40
+ background-color: #dafbe1;
41
+ }
42
+ .sc-highlight .kc {
43
+ color: #0550ae;
44
+ }
45
+ .sc-highlight .l, .sc-highlight .ld, .sc-highlight .m, .sc-highlight .mb, .sc-highlight .mf, .sc-highlight .mh, .sc-highlight .mi, .sc-highlight .il, .sc-highlight .mo, .sc-highlight .mx {
46
+ color: #0550ae;
47
+ }
48
+ .sc-highlight .sb {
49
+ color: #0550ae;
50
+ }
51
+ .sc-highlight .bp {
52
+ color: #0550ae;
53
+ }
54
+ .sc-highlight .ne {
55
+ color: #0550ae;
56
+ }
57
+ .sc-highlight .nl {
58
+ color: #0550ae;
59
+ }
60
+ .sc-highlight .py {
61
+ color: #0550ae;
62
+ }
63
+ .sc-highlight .nv, .sc-highlight .vc, .sc-highlight .vg, .sc-highlight .vi, .sc-highlight .vm {
64
+ color: #0550ae;
65
+ }
66
+ .sc-highlight .o, .sc-highlight .ow {
67
+ color: #0550ae;
68
+ }
69
+ .sc-highlight .gh {
70
+ color: #0550ae;
71
+ font-weight: bold;
72
+ }
73
+ .sc-highlight .gu {
74
+ color: #0550ae;
75
+ font-weight: bold;
76
+ }
77
+ .sc-highlight .s, .sc-highlight .sa, .sc-highlight .sc, .sc-highlight .dl, .sc-highlight .sd, .sc-highlight .s2, .sc-highlight .se, .sc-highlight .sh, .sc-highlight .sx, .sc-highlight .s1, .sc-highlight .ss {
78
+ color: #0a3069;
79
+ }
80
+ .sc-highlight .nd {
81
+ color: #8250df;
82
+ }
83
+ .sc-highlight .nf, .sc-highlight .fm {
84
+ color: #8250df;
85
+ }
86
+ .sc-highlight .err {
87
+ color: #f6f8fa;
88
+ background-color: #82071e;
89
+ }
90
+ .sc-highlight .c, .sc-highlight .ch, .sc-highlight .cd, .sc-highlight .cm, .sc-highlight .cp, .sc-highlight .cpf, .sc-highlight .c1, .sc-highlight .cs {
91
+ color: #6e7781;
92
+ }
93
+ .sc-highlight .gl {
94
+ color: #6e7781;
95
+ }
96
+ .sc-highlight .gt {
97
+ color: #6e7781;
98
+ }
99
+ .sc-highlight .ni {
100
+ color: #24292f;
101
+ }
102
+ .sc-highlight .si {
103
+ color: #24292f;
104
+ }
105
+ .sc-highlight .ge {
106
+ color: #24292f;
107
+ font-style: italic;
108
+ }
109
+ .sc-highlight .gs {
110
+ color: #24292f;
111
+ font-weight: bold;
112
+ }
@@ -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
- root? ? "Previews" : id
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).tap { _1.index(...) }.ordered_children
29
- end
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)
@@ -2,9 +2,9 @@ class Showcase::Sample
2
2
  attr_reader :name, :id, :events, :details
3
3
  attr_reader :source, :instrumented
4
4
 
5
- def initialize(view_context, name, description: nil, id: name.parameterize, events: nil, **details)
5
+ def initialize(view_context, name, description: nil, id: name.parameterize, syntax: :erb, events: nil, **details)
6
6
  @view_context = view_context
7
- @name, @id, @details = name, id, details
7
+ @name, @id, @syntax, @details = name, id, syntax, details
8
8
  @events = Array(events)
9
9
  description description if description
10
10
  end
@@ -34,13 +34,13 @@ class Showcase::Sample
34
34
  end
35
35
 
36
36
  def extract(&block)
37
- lines = extract_block_lines_via_matched_indentation_from(*block.source_location)
38
- @source = @view_context.instance_exec(lines, &Showcase.sample_renderer)
37
+ source = extract_source_block_via_matched_indentation_from(*block.source_location)
38
+ @source = @view_context.instance_exec(source, @syntax, &Showcase.sample_renderer)
39
39
  end
40
40
 
41
41
  private
42
42
 
43
- def extract_block_lines_via_matched_indentation_from(file, starting_index)
43
+ def extract_source_block_via_matched_indentation_from(file, starting_index)
44
44
  first_line, *lines = File.readlines(file).from(starting_index - 1)
45
45
 
46
46
  indentation = first_line.match(/^\s+(?=\b)/).to_s
@@ -48,6 +48,6 @@ class Showcase::Sample
48
48
 
49
49
  index = lines.index { _1.match?(matcher) }
50
50
  lines.slice!(index..) if index
51
- lines
51
+ lines.join.strip_heredoc
52
52
  end
53
53
  end
@@ -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>
@@ -1,4 +1,4 @@
1
- <div class="sc-space-y-8">
1
+ <div class="sc-space-y-8" id="<%= preview.id %>">
2
2
  <section>
3
3
  <% if preview.title %>
4
4
  <div class="sc-flex sc-items-center sc-space-x-2 sc-mb-2">
@@ -27,8 +27,8 @@
27
27
  <details>
28
28
  <summary class="sc-px-4 sc-py-2 hover:sc-bg-indigo-50 sc-cursor-pointer sc-select-none">View Source</summary>
29
29
 
30
- <section class="sc-px-4 sc-py-2 sc-relative sc-overflow-y-auto hover:sc-select-all">
31
- <%= sample.source %>
30
+ <section class="sc-highlight sc-px-4 sc-py-2 sc-relative sc-overflow-y-auto hover:sc-select-all">
31
+ <pre><%= sample.source %></pre>
32
32
  </section>
33
33
  </details>
34
34
  <% end %>
@@ -1 +1 @@
1
- <%= stylesheet_link_tag "application", "showcase" %>
1
+ <%= stylesheet_link_tag "application", "showcase", "showcase.highlights" %>
@@ -1,3 +1,3 @@
1
1
  <article class="hover:sc-bg-indigo-50 <%= "sc-bg-indigo-50" if path.id == params[:id] %>">
2
- <%= link_to path.basename.titleize, preview_path(path.id), class: "sc-inline-block sc-py-2 sc-px-8 sc-w-full" %>
2
+ <%= link_to path.basename.titleize, preview_path(path.id), class: "sc-inline-block sc-py-2 sc-px-8 sc-w-full hover:sc-text-inherit hover:sc-no-underline" %>
3
3
  </article>
@@ -6,8 +6,8 @@ module Showcase
6
6
  config.assets.precompile += %w[showcase_manifest]
7
7
  end
8
8
 
9
- initializer "showcase.integration_test.autorun" do
10
- Showcase::IntegrationTest.autorun if Rails.env.test?
9
+ initializer "showcase.previews_test.autorun" do
10
+ Showcase::PreviewsTest.autorun if Rails.env.test?
11
11
  end
12
12
  end
13
13
  end
@@ -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
@@ -0,0 +1,45 @@
1
+ class Showcase::PreviewsTest < ActionView::TestCase
2
+ def self.inherited(test_class)
3
+ super
4
+ test_class.prepare
5
+ end
6
+
7
+ def self.autorun
8
+ at_exit { prepare unless subclasses.any? }
9
+ end
10
+
11
+ def self.prepare
12
+ tests Showcase::EngineController._helpers
13
+
14
+ tree = Showcase::Path.tree
15
+ tree.flat_map(&:ordered_paths).each do |path|
16
+ test "Showcase: automatically renders showcase/previews/#{path.id}" do
17
+ render "showcase/engine/preview", preview: path.preview_for(view)
18
+ assert_showcase_preview(path.id)
19
+ end
20
+ end
21
+
22
+ test "Showcase: isn't empty" do
23
+ assert_not_empty tree, "Showcase couldn't find any samples to generate tests for"
24
+ end
25
+ end
26
+
27
+ def self.test(name = nil, showcase: nil, id: nil, &block)
28
+ case
29
+ when name then super(name, &block)
30
+ when id && showcase.nil? then raise ArgumentError, "can't test a sample without a showcase"
31
+ else
32
+ super "Showcase: showcase/previews/#{showcase} #{"sample #{id}" if id}".squish do
33
+ path = Showcase::Path.new(showcase)
34
+ render "showcase/engine/preview", preview: path.preview_for(view)
35
+
36
+ assert_showcase_preview(path.id)
37
+ assert_element(id: id || path.id) { instance_eval(&block) }
38
+ end
39
+ end
40
+ end
41
+
42
+ # Override `assert_showcase_preview` to add custom assertions.
43
+ def assert_showcase_preview(id)
44
+ end
45
+ end
@@ -1,3 +1,3 @@
1
1
  module Showcase
2
- VERSION = "0.2.2"
2
+ VERSION = "0.2.4"
3
3
  end
data/lib/showcase.rb CHANGED
@@ -1,11 +1,28 @@
1
1
  require_relative "showcase/version"
2
2
 
3
+ # Activate the app-bundled Rouge gem to setup default syntax highlighting.
4
+ begin
5
+ gem "rouge"
6
+ require "rouge"
7
+ rescue LoadError
8
+ end
9
+
3
10
  module Showcase
4
- autoload :IntegrationTest, "showcase/integration_test"
5
- autoload :RouteHelper, "showcase/route_helper"
11
+ autoload :PreviewsTest, "showcase/previews_test"
12
+ autoload :RouteHelper, "showcase/route_helper"
13
+ autoload :Options, "showcase/options"
6
14
 
7
15
  singleton_class.attr_accessor :sample_renderer
8
- @sample_renderer = ->(lines) { tag.pre lines.join.strip_heredoc }
16
+ @sample_renderer = proc { _1 }
17
+
18
+ if defined?(Rouge)
19
+ Formatter = Rouge::Formatters::HTML.new
20
+
21
+ @sample_renderer = ->(source, syntax) do
22
+ lexed = Rouge::Lexer.find(syntax).lex(source)
23
+ Showcase::Formatter.format(lexed).html_safe
24
+ end
25
+ end
9
26
 
10
27
  singleton_class.attr_reader :previews_path
11
28
  @previews_path = "showcase/previews"
@@ -15,6 +32,38 @@ module Showcase
15
32
  Dir.glob("**/*.*", base: File.join(root, previews_path))
16
33
  end.uniq
17
34
  end
35
+
36
+ def self.options
37
+ Options
38
+ end
39
+
40
+ options.define :stimulus do
41
+ def targets(name, ...)
42
+ option(%(data-#{@controller}-target="#{name}"), ...)
43
+ end
44
+
45
+ def values(name, ...)
46
+ option("data-#{@controller}-#{name}-value", ...)
47
+ end
48
+
49
+ def classes(name, ...)
50
+ option("data-#{@controller}-#{name}-class", ...)
51
+ end
52
+
53
+ def outlet(name, ...)
54
+ option("data-#{@controller}-#{name}-outlet", ...)
55
+ end
56
+
57
+ def action(name, ...)
58
+ option(%(data-action="#{name}"), ...)
59
+ end
60
+ end
61
+
62
+ options.define :nice_partials do
63
+ def content_block(*arguments, **options, &block)
64
+ option(*arguments, **options, type: "Content Block", &block)
65
+ end
66
+ end
18
67
  end
19
68
 
20
69
  require "showcase/engine" if defined?(Rails::Engine)
@@ -1,14 +1,14 @@
1
1
  namespace :showcase do
2
2
  namespace :install do
3
- INTEGRATION_TEST_PATH = "test/integration/showcase_test.rb"
3
+ PREVIEWS_TEST_PATH = "test/views/showcase_test.rb"
4
4
 
5
- desc "Install Showcase integration testing in #{INTEGRATION_TEST_PATH}"
6
- task :integration_test do
7
- mkdir_p File.dirname(INTEGRATION_TEST_PATH)
8
- File.write INTEGRATION_TEST_PATH, <<~RUBY
5
+ desc "Install Showcase previews testing in #{PREVIEWS_TEST_PATH}"
6
+ task :previews_test do
7
+ mkdir_p File.dirname(PREVIEWS_TEST_PATH)
8
+ File.write PREVIEWS_TEST_PATH, <<~RUBY
9
9
  require "test_helper"
10
10
 
11
- class ShowcaseTest < Showcase::IntegrationTest
11
+ class ShowcaseTest < Showcase::PreviewsTest
12
12
  def assert_showcase_preview(id)
13
13
  # Add any custom preview response body assertions here.
14
14
  end
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.2
4
+ version: 0.2.4
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-13 00:00:00.000000000 Z
12
+ date: 2023-03-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -50,11 +50,11 @@ files:
50
50
  - README.md
51
51
  - Rakefile
52
52
  - app/assets/builds/showcase.css
53
+ - app/assets/builds/showcase.highlights.css
53
54
  - app/assets/config/showcase_manifest.js
54
55
  - app/assets/javascripts/showcase.js
55
56
  - app/controllers/showcase/engine_controller.rb
56
57
  - app/controllers/showcase/previews_controller.rb
57
- - app/models/showcase/options.rb
58
58
  - app/models/showcase/path.rb
59
59
  - app/models/showcase/preview.rb
60
60
  - app/models/showcase/sample.rb
@@ -74,7 +74,8 @@ files:
74
74
  - lib/showcase-rails.rb
75
75
  - lib/showcase.rb
76
76
  - lib/showcase/engine.rb
77
- - lib/showcase/integration_test.rb
77
+ - lib/showcase/options.rb
78
+ - lib/showcase/previews_test.rb
78
79
  - lib/showcase/route_helper.rb
79
80
  - lib/showcase/version.rb
80
81
  - lib/tasks/showcase_tasks.rake
@@ -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
@@ -1,30 +0,0 @@
1
- class Showcase::IntegrationTest < ActionDispatch::IntegrationTest
2
- def self.inherited(test_class)
3
- super
4
- test_class.prepare
5
- end
6
-
7
- def self.autorun
8
- at_exit { prepare unless subclasses.any? }
9
- end
10
-
11
- def self.prepare
12
- tree = Showcase::Path.tree
13
- tree.flat_map(&:ordered_paths).each do |path|
14
- test "Showcase: GET showcase/previews/#{path.id} renders successfully" do
15
- get showcase.preview_path(path.id)
16
-
17
- assert_response :ok
18
- assert_showcase_preview(path.id)
19
- end
20
- end
21
-
22
- test "Showcase: isn't empty" do
23
- assert_not_empty tree, "Showcase couldn't find any samples to generate tests for"
24
- end
25
- end
26
-
27
- # Override `assert_showcase_preview` to add custom assertions.
28
- def assert_showcase_preview(id)
29
- end
30
- end