super 0.0.6 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -0
  3. data/CONTRIBUTING.md +56 -0
  4. data/README.md +55 -57
  5. data/Rakefile +16 -14
  6. data/STABILITY.md +50 -0
  7. data/app/assets/javascripts/super/application.js +297 -97
  8. data/app/assets/stylesheets/super/application.css +5600 -0
  9. data/app/controllers/super/application_controller.rb +15 -6
  10. data/app/helpers/super/form_builder_helper.rb +25 -0
  11. data/app/views/layouts/super/application.html.erb +22 -6
  12. data/app/views/super/application/_display_rich_text.html.erb +1 -0
  13. data/app/views/super/application/_filter.html.erb +6 -0
  14. data/app/views/super/application/_filter_type_select.html.erb +21 -0
  15. data/app/views/super/application/_filter_type_text.html.erb +18 -0
  16. data/app/views/super/application/_filter_type_timestamp.html.erb +24 -0
  17. data/app/views/super/application/_form_field__destroy.html.erb +1 -9
  18. data/app/views/super/application/_form_field_checkbox.html.erb +1 -0
  19. data/app/views/super/application/_form_field_rich_text_area.html.erb +1 -0
  20. data/app/views/super/application/_form_field_select.html.erb +1 -23
  21. data/app/views/super/application/_form_field_text.html.erb +1 -13
  22. data/app/views/super/application/_query.html.erb +18 -0
  23. data/app/views/super/application/_sort.html.erb +18 -0
  24. data/app/views/super/application/_sort_expression.html.erb +25 -0
  25. data/app/views/super/application/_super_layout.html.erb +5 -5
  26. data/app/views/super/application/_super_pagination.html.erb +16 -0
  27. data/app/views/super/application/_super_panel.html.erb +2 -2
  28. data/app/views/super/application/_super_schema_display_index.html.erb +9 -24
  29. data/app/views/super/application/_super_schema_display_show.html.erb +4 -4
  30. data/app/views/super/application/_super_schema_form.html.erb +3 -3
  31. data/app/views/super/application/edit.html.erb +2 -6
  32. data/app/views/super/application/index.html.erb +2 -6
  33. data/app/views/super/application/new.html.erb +2 -6
  34. data/app/views/super/application/show.html.erb +2 -6
  35. data/app/views/super/feather/README.md +1 -0
  36. data/app/views/super/feather/_x.html +15 -0
  37. data/config/routes.rb +2 -0
  38. data/docs/README.md +4 -2
  39. data/docs/action_text.md +48 -0
  40. data/docs/cheat.md +8 -8
  41. data/docs/faq.md +3 -3
  42. data/docs/installation.md +21 -0
  43. data/docs/quick_start.md +1 -16
  44. data/docs/webpacker.md +13 -5
  45. data/docs/yard_customizations.rb +2 -0
  46. data/frontend/super-frontend/dist/application.css +5600 -0
  47. data/frontend/super-frontend/dist/application.js +297 -97
  48. data/lib/generators/super/action_text/USAGE +23 -0
  49. data/lib/generators/super/action_text/action_text_generator.rb +32 -0
  50. data/lib/generators/super/action_text/templates/pack_super_action_text.css +23 -0
  51. data/lib/generators/super/action_text/templates/pack_super_action_text.js +4 -0
  52. data/lib/generators/super/install/install_generator.rb +2 -0
  53. data/lib/generators/super/resource/resource_generator.rb +2 -0
  54. data/lib/generators/super/resource/templates/resources_controller.rb.tt +1 -31
  55. data/lib/generators/super/webpacker/USAGE +5 -4
  56. data/lib/generators/super/webpacker/webpacker_generator.rb +5 -2
  57. data/lib/super.rb +23 -2
  58. data/lib/super/action_inquirer.rb +2 -0
  59. data/lib/super/assets.rb +114 -38
  60. data/lib/super/client_error.rb +2 -0
  61. data/lib/super/compatibility.rb +15 -1
  62. data/lib/super/configuration.rb +22 -69
  63. data/lib/super/controls.rb +6 -25
  64. data/lib/super/controls/optional.rb +71 -24
  65. data/lib/super/controls/required.rb +3 -29
  66. data/lib/super/controls/steps.rb +44 -53
  67. data/lib/super/controls/view.rb +55 -0
  68. data/lib/super/display.rb +80 -0
  69. data/lib/super/display/guesser.rb +36 -0
  70. data/lib/super/display/schema_types.rb +28 -33
  71. data/lib/super/engine.rb +11 -1
  72. data/lib/super/error.rb +14 -0
  73. data/lib/super/filter.rb +14 -0
  74. data/lib/super/filter/form_object.rb +94 -0
  75. data/lib/super/filter/guesser.rb +32 -0
  76. data/lib/super/filter/operator.rb +105 -0
  77. data/lib/super/filter/schema_types.rb +114 -0
  78. data/lib/super/form.rb +29 -40
  79. data/lib/super/form/builder.rb +206 -0
  80. data/lib/super/form/guesser.rb +29 -0
  81. data/lib/super/form/inline_errors.rb +28 -0
  82. data/lib/super/form/schema_types.rb +31 -29
  83. data/lib/super/form/strong_params.rb +31 -0
  84. data/lib/super/layout.rb +2 -0
  85. data/lib/super/link.rb +2 -0
  86. data/lib/super/navigation/automatic.rb +2 -0
  87. data/lib/super/pagination.rb +57 -0
  88. data/lib/super/panel.rb +2 -0
  89. data/lib/super/partial.rb +14 -0
  90. data/lib/super/partial/resolving.rb +2 -0
  91. data/lib/super/plugin.rb +36 -63
  92. data/lib/super/query/form_object.rb +48 -0
  93. data/lib/super/schema.rb +2 -24
  94. data/lib/super/schema/common.rb +27 -0
  95. data/lib/super/schema/guesser.rb +79 -0
  96. data/lib/super/sort.rb +110 -0
  97. data/lib/super/version.rb +3 -1
  98. data/lib/super/view_helper.rb +2 -19
  99. metadata +74 -22
  100. data/app/helpers/super/application_helper.rb +0 -39
  101. data/app/views/super/application/_form_inline_errors.html.erb +0 -10
  102. data/frontend/super-frontend/build.js +0 -36
  103. data/frontend/super-frontend/package.json +0 -21
  104. data/frontend/super-frontend/postcss.config.js +0 -6
  105. data/frontend/super-frontend/src/javascripts/super/application.ts +0 -18
  106. data/frontend/super-frontend/src/javascripts/super/apply_template_controller.ts +0 -19
  107. data/frontend/super-frontend/src/javascripts/super/rails__ujs.d.ts +0 -1
  108. data/frontend/super-frontend/src/javascripts/super/toggle_pending_destruction_controller.ts +0 -15
  109. data/frontend/super-frontend/src/stylesheets/super/application.css +0 -77
  110. data/frontend/super-frontend/tailwind.config.js +0 -15
  111. data/frontend/super-frontend/tsconfig.json +0 -13
  112. data/frontend/super-frontend/yarn.lock +0 -5448
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Super
4
+ class ActionTextGenerator < Rails::Generators::Base
5
+ source_root File.expand_path("templates", __dir__)
6
+
7
+ def copy_the_pack_files
8
+ template(
9
+ "pack_super_action_text.js",
10
+ "app/javascript/packs/super/action_text.js"
11
+ )
12
+ template(
13
+ "pack_super_action_text.css",
14
+ "app/javascript/packs/super/action_text.css"
15
+ )
16
+ end
17
+
18
+ def add_action_text_assets_to_config
19
+ insert_into_file(
20
+ "config/initializers/super.rb",
21
+ " c.javascripts.push(Super::Assets.webpacker(\"super/action_text\"))\n" \
22
+ " c.stylesheets.push(Super::Assets.webpacker(\"super/action_text\"))\n",
23
+ before: /\bend\b/
24
+ )
25
+ end
26
+
27
+ def remind_about_webpacker
28
+ say "Make sure Webpacker is set up on your application!", :bold
29
+ say "Run if needed: bundle exec rails webpacker:install"
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,23 @@
1
+ @import "trix/dist/trix";
2
+
3
+ /* This is the SCSS that the ActionText installation generator adds, compiled to CSS */
4
+ .trix-content .attachment-gallery > action-text-attachment,
5
+ .trix-content .attachment-gallery > .attachment {
6
+ flex: 1 0 33%;
7
+ padding: 0 0.5em;
8
+ max-width: 33%; }
9
+ .trix-content .attachment-gallery.attachment-gallery--2 > action-text-attachment,
10
+ .trix-content .attachment-gallery.attachment-gallery--2 > .attachment,
11
+ .trix-content .attachment-gallery.attachment-gallery--4 > action-text-attachment,
12
+ .trix-content .attachment-gallery.attachment-gallery--4 > .attachment {
13
+ flex-basis: 50%;
14
+ max-width: 50%; }
15
+ .trix-content action-text-attachment .attachment {
16
+ padding: 0 !important;
17
+ max-width: 100% !important; }
18
+
19
+ /* This is for getting Tailwind to work with Trix */
20
+ .trix-content ul {
21
+ list-style-type: disc; }
22
+ .trix-content ol {
23
+ list-style-type: decimal; }
@@ -0,0 +1,4 @@
1
+ import * as ActiveStorage from "@rails/activestorage"
2
+ ActiveStorage.start()
3
+ require("trix")
4
+ require("@rails/actiontext")
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  class InstallGenerator < Rails::Generators::Base
3
5
  source_root File.expand_path("templates", __dir__)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  class ResourceGenerator < Rails::Generators::NamedBase
3
5
  source_root File.expand_path("templates", __dir__)
@@ -6,40 +6,10 @@ class <%= class_name.pluralize %>Controller < <%= parent_controller_name %>
6
6
  Controls.new
7
7
  end
8
8
 
9
- class Controls
10
- def title
11
- <%= class_name %>.name.pluralize
12
- end
13
-
9
+ class Controls < Super::Controls
14
10
  def model
15
11
  <%= class_name %>
16
12
  end
17
-
18
- def scope(action:)
19
- if action.read?
20
- <%= class_name %>.all
21
- else
22
- <%= class_name %>.all
23
- end
24
- end
25
-
26
- def permitted_params(params, action:)
27
- if action.create?
28
- params.require(:<%= file_name %>).permit()
29
- else
30
- params.require(:<%= file_name %>).permit()
31
- end
32
- end
33
-
34
- def display_schema(action:)
35
- Super::Schema.new(Super::Display::SchemaTypes.new) do |fields, type|
36
- end
37
- end
38
-
39
- def form_schema(action:)
40
- Super::Schema.new(Super::Form::SchemaTypes.new) do |fields, type|
41
- end
42
- end
43
13
  end
44
14
  end
45
15
  <% end -%>
@@ -1,14 +1,15 @@
1
1
  Description:
2
2
  Creates the necessary files for assets to be served under Webpacker
3
3
 
4
- Webpacker support requires ERB support. There are no other dependencies.
4
+ Webpacker support requires that you install ERB support for Webpacker.
5
5
 
6
6
  Installing ERB on webpacker is usually done by running the command:
7
7
  `rails webpacker:install:erb`
8
8
 
9
9
  Example:
10
10
  rails webpacker:install:erb # if you hadn't set up ERB already
11
- rails generate super:install:webpacker
11
+ rails generate super:webpacker
12
12
 
13
- This will create:
14
- app/javascript/packs/super/application.js.erb
13
+ This will:
14
+ Create app/javascript/packs/super/application.js.erb
15
+ Modify config/initializers/super.rb
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  class WebpackerGenerator < Rails::Generators::Base
3
5
  source_root File.expand_path("templates", __dir__)
@@ -12,14 +14,15 @@ module Super
12
14
  def set_asset_handler_to_webpacker
13
15
  insert_into_file(
14
16
  "config/initializers/super.rb",
15
- " c.asset_handler = Super::Assets.webpacker\n",
17
+ " c.javascripts = Super::Assets.use_webpacker(c.javascripts)\n" \
18
+ " c.stylesheets = Super::Assets.use_webpacker(c.stylesheets)\n",
16
19
  before: /\bend\b/
17
20
  )
18
21
  end
19
22
 
20
23
  def remind_about_erb
21
24
  say "Make sure ERB is set up for Webpacker!", :bold
22
- say "Run if needed: rails webpacker:install:erb", :bold
25
+ say "Run if needed: bundle exec rails webpacker:install:erb"
23
26
  end
24
27
  end
25
28
  end
data/lib/super.rb CHANGED
@@ -1,4 +1,10 @@
1
- require "active_support/concern"
1
+ # frozen_string_literal: true
2
+
3
+ require "tsort"
4
+
5
+ require "rails/engine"
6
+
7
+ require "super/schema/common"
2
8
 
3
9
  require "super/action_inquirer"
4
10
  require "super/assets"
@@ -6,11 +12,21 @@ require "super/client_error"
6
12
  require "super/compatibility"
7
13
  require "super/configuration"
8
14
  require "super/controls"
15
+ require "super/display"
16
+ require "super/display/guesser"
9
17
  require "super/display/schema_types"
10
- require "super/engine"
11
18
  require "super/error"
19
+ require "super/filter"
20
+ require "super/filter/form_object"
21
+ require "super/filter/guesser"
22
+ require "super/filter/operator"
23
+ require "super/filter/schema_types"
12
24
  require "super/form"
25
+ require "super/form/builder"
26
+ require "super/form/guesser"
27
+ require "super/form/inline_errors"
13
28
  require "super/form/schema_types"
29
+ require "super/form/strong_params"
14
30
  require "super/layout"
15
31
  require "super/link"
16
32
  require "super/navigation/automatic"
@@ -18,6 +34,11 @@ require "super/pagination"
18
34
  require "super/panel"
19
35
  require "super/partial"
20
36
  require "super/plugin"
37
+ require "super/query/form_object"
21
38
  require "super/schema"
39
+ require "super/schema/guesser"
40
+ require "super/sort"
22
41
  require "super/version"
23
42
  require "super/view_helper"
43
+
44
+ require "super/engine"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  # ```ruby
3
5
  # action = Super::ActionInquirer.new(
data/lib/super/assets.rb CHANGED
@@ -1,8 +1,66 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  # Utilities for determining whether to use Sprockets or Webpacker
3
5
  class Assets
4
- def self.sprockets_available?
5
- Gem::Dependency.new("sprockets").matching_specs.any?
6
+ def self.webpacker(path, **arguments)
7
+ Asset.new(handler: Handler.webpacker, path: path, arguments: arguments)
8
+ end
9
+
10
+ def self.sprockets(path, **arguments)
11
+ Asset.new(handler: Handler.sprockets, path: path, arguments: arguments)
12
+ end
13
+
14
+ def self.auto(path, **arguments)
15
+ Asset.new(handler: Handler.auto, path: path, arguments: arguments)
16
+ end
17
+
18
+ def self.use_webpacker(assets, grep: nil)
19
+ assets = [assets] if !assets.kind_of?(Array)
20
+
21
+ assets.map do |asset|
22
+ grep_matches = grep && asset === grep
23
+ if grep_matches || !grep
24
+ asset.instance_variable_set(:@handler, Handler.webpacker)
25
+ end
26
+
27
+ asset
28
+ end
29
+ end
30
+
31
+ def self.use_sprockets(assets, grep: nil)
32
+ assets = [assets] if !assets.kind_of?(Array)
33
+
34
+ assets.map do |asset|
35
+ grep_matches = grep && asset === grep
36
+ if grep_matches || !grep
37
+ asset.instance_variable_set(:@asset_handler, Handler.sprockets)
38
+ end
39
+
40
+ asset
41
+ end
42
+ end
43
+
44
+ class Asset
45
+ def initialize(handler:, path:, arguments:)
46
+ @handler = handler
47
+ @path = path
48
+ @arguments = arguments
49
+ end
50
+
51
+ attr_reader :handler
52
+ attr_reader :path
53
+ attr_reader :arguments
54
+
55
+ def ===(other)
56
+ return true if path == other
57
+ return true if other.is_a?(Regexp) && path.match?(other)
58
+ return true if handler == other
59
+ return true if handler.to_sym == other
60
+ return true if handler.to_s == other
61
+
62
+ false
63
+ end
6
64
  end
7
65
 
8
66
  def self.dist(gem_name, package_name)
@@ -15,49 +73,67 @@ module Super
15
73
  gem_path.join("frontend", package_name, "dist")
16
74
  end
17
75
 
18
- def self.auto
19
- @auto ||=
20
- if Gem::Dependency.new("sprockets", "~> 4.0").matching_specs.any?
21
- sprockets
22
- elsif Gem::Dependency.new("sprockets", "~> 3.0").matching_specs.any?
23
- sprockets
24
- elsif Gem::Dependency.new("sprockets", "~> 2.0").matching_specs.any?
25
- sprockets
26
- elsif Gem::Dependency.new("webpacker", "~> 4.0").matching_specs.any?
27
- webpacker
28
- elsif Gem::Dependency.new("webpacker", "~> 3.0").matching_specs.any?
29
- webpacker
30
- else
31
- none
32
- end
33
- end
76
+ class Handler
77
+ def self.auto
78
+ @auto ||=
79
+ if Gem::Dependency.new("sprockets", "~> 4.0").matching_specs.any?
80
+ sprockets
81
+ elsif Gem::Dependency.new("sprockets", "~> 3.0").matching_specs.any?
82
+ sprockets
83
+ elsif Gem::Dependency.new("sprockets", "~> 2.0").matching_specs.any?
84
+ sprockets
85
+ elsif Gem::Dependency.new("webpacker", "~> 6.0").matching_specs.any?
86
+ webpacker
87
+ elsif Gem::Dependency.new("webpacker", "~> 5.0").matching_specs.any?
88
+ webpacker
89
+ elsif Gem::Dependency.new("webpacker", "~> 4.0").matching_specs.any?
90
+ webpacker
91
+ elsif Gem::Dependency.new("webpacker", "~> 3.0").matching_specs.any?
92
+ webpacker
93
+ else
94
+ none
95
+ end
96
+ end
34
97
 
35
- def self.sprockets
36
- new(:sprockets)
37
- end
98
+ def self.sprockets_available?
99
+ Gem::Dependency.new("sprockets").matching_specs.any? && defined?(Sprockets)
100
+ end
38
101
 
39
- def self.webpacker
40
- new(:webpacker)
41
- end
102
+ def self.sprockets
103
+ @sprockets ||= new(:sprockets)
104
+ end
42
105
 
43
- def self.none
44
- new(:none)
45
- end
106
+ def self.webpacker
107
+ @webpacker ||= new(:webpacker)
108
+ end
46
109
 
47
- def initialize(asset_handler)
48
- @asset_handler = asset_handler
49
- end
110
+ def self.none
111
+ @none ||= new(:none)
112
+ end
50
113
 
51
- def sprockets?
52
- @asset_handler == :sprockets
53
- end
114
+ def initialize(asset_handler)
115
+ @asset_handler = asset_handler
116
+ end
54
117
 
55
- def webpacker?
56
- @asset_handler == :webpacker
57
- end
118
+ def sprockets?
119
+ @asset_handler == :sprockets
120
+ end
121
+
122
+ def webpacker?
123
+ @asset_handler == :webpacker
124
+ end
125
+
126
+ def none?
127
+ @asset_handler == :none
128
+ end
129
+
130
+ def to_sym
131
+ @asset_handler
132
+ end
58
133
 
59
- def none?
60
- @asset_handler == :none
134
+ def to_s
135
+ @asset_handler.to_s
136
+ end
61
137
  end
62
138
  end
63
139
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  # A container class for all user-facing (4xx) errors thrown by this library.
3
5
  #
@@ -1,13 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  module Compatability
3
5
  module_function
4
6
 
5
- def rails_50_errable_fields(field)
7
+ # Rails 5.1 and after lets you find field errors using either a string or a
8
+ # symbol.
9
+ def errable_fields(field)
6
10
  if Rails::VERSION::MAJOR == 5 && Rails::VERSION::MINOR == 0
7
11
  [field.to_s, field.to_sym]
8
12
  else
9
13
  field
10
14
  end
11
15
  end
16
+
17
+ def sanitize_sql_like(query)
18
+ if ActiveRecord::VERSION::MAJOR == 4
19
+ ActiveRecord::Base.send(:sanitize_sql_like, query)
20
+ elsif ActiveRecord::VERSION::MAJOR == 5 && ActiveRecord::VERSION::MINOR <= 1
21
+ ActiveRecord::Base.send(:sanitize_sql_like, query)
22
+ else
23
+ ActiveRecord::Base.sanitize_sql_like(query)
24
+ end
25
+ end
12
26
  end
13
27
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  # @yield [Configuration]
3
5
  # @return [Configuration]
@@ -19,81 +21,32 @@ module Super
19
21
  # end
20
22
  # ```
21
23
  class Configuration
22
- module ConfigurationLogic # @api private
23
- def self.included(base)
24
- base.extend(ClassMethods)
25
- end
26
-
27
- def initialize
28
- self.class.defaults.each do |key, value|
29
- if value.respond_to?(:call)
30
- value = value.call
31
- end
32
-
33
- public_send("#{key}=", value)
34
- end
35
- end
36
-
37
- def configured?(attr)
38
- instance_variable_defined?("@#{attr}")
39
- end
40
-
41
- module ClassMethods
42
- def defaults
43
- @defaults ||= {}
44
- end
45
-
46
- def wraps
47
- @wraps ||= {}
48
- end
24
+ def initialize
25
+ self.title = "Super Admin"
26
+ self.index_records_per_page = 20
27
+ self.controller_namespace = "admin"
28
+ self.route_namespace = :admin
49
29
 
50
- def configure(attr, wrap: nil, enum: nil, **kwargs)
51
- if kwargs.key?(:default)
52
- defaults[attr] = kwargs[:default]
53
- end
30
+ controller_plugins.use(prepend: Super::Pagination::ControllerMethods)
54
31
 
55
- define_method(attr) do
56
- if !configured?(attr)
57
- raise Error::UnconfiguredConfiguration, "unconfigured: #{attr}"
58
- end
59
-
60
- result = instance_variable_get("@#{attr}")
61
-
62
- if wrap.nil?
63
- result
64
- else
65
- wrap.call(result)
66
- end
67
- end
68
-
69
- define_method("#{attr}=") do |value|
70
- if enum.is_a?(Array)
71
- if !enum.include?(value)
72
- raise Error::InvalidConfiguration,
73
- "tried to set `#{attr}` to `#{value.inspect}`, " \
74
- "expected: #{enum.join(", ")}"
75
- end
76
- end
32
+ self.javascripts = [Super::Assets.auto("super/application")]
33
+ self.stylesheets = [Super::Assets.auto("super/application")]
34
+ end
77
35
 
78
- instance_variable_set("@#{attr}", value)
79
- value
80
- end
81
- end
82
- end
36
+ attr_accessor :title
37
+ attr_accessor :index_records_per_page
38
+ attr_accessor :controller_namespace
39
+ attr_writer :route_namespace
40
+ def route_namespace
41
+ [@route_namespace].flatten
83
42
  end
84
43
 
85
- include ConfigurationLogic
44
+ attr_accessor :javascripts
45
+ attr_accessor :stylesheets
86
46
 
87
- # @!attribute [rw]
88
- configure :title
89
- # @!attribute [rw]
90
- configure :index_records_per_page, default: 20
91
- # @!attribute [rw]
92
- configure :controller_namespace, default: "admin"
93
- # @!attribute [rw]
94
- configure :route_namespace, default: :admin, wrap: -> (val) { [val].flatten }
95
- # @!attribute [rw]
96
- configure :asset_handler, default: -> { Super::Assets.auto }
47
+ def controller_plugins
48
+ Plugin::Registry.controller
49
+ end
97
50
 
98
51
  # @api private
99
52
  def path_parts(*parts)