skeleton-loader 0.1.0

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.
Files changed (31) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +401 -0
  4. data/app/assets/javascripts/skeleton_loader.js +2 -0
  5. data/app/assets/javascripts/skeleton_loader.js.LICENSE.txt +1 -0
  6. data/app/assets/stylesheets/skeleton_loader.css +83 -0
  7. data/app/controllers/skeleton_loader/skeleton_loader_controller.rb +60 -0
  8. data/app/javascript/client_skeleton_loader.js +234 -0
  9. data/app/javascript/server_skeleton_loader.js +113 -0
  10. data/app/javascript/skeleton_loader.js +6 -0
  11. data/config/routes.rb +5 -0
  12. data/lib/generators/skeleton_loader/add_templates_generator.rb +16 -0
  13. data/lib/generators/skeleton_loader/reset_templates_generator.rb +16 -0
  14. data/lib/generators/skeleton_loader/templates/_card.html.erb +31 -0
  15. data/lib/generators/skeleton_loader/templates/_comment.html.erb +61 -0
  16. data/lib/generators/skeleton_loader/templates/_default.html.erb +23 -0
  17. data/lib/generators/skeleton_loader/templates/_gallery.html.erb +19 -0
  18. data/lib/generators/skeleton_loader/templates/_paragraph.html.erb +28 -0
  19. data/lib/generators/skeleton_loader/templates/_product.html.erb +49 -0
  20. data/lib/generators/skeleton_loader/templates/_profile.html.erb +28 -0
  21. data/lib/skeleton-loader.rb +7 -0
  22. data/lib/skeleton_loader/configuration.rb +68 -0
  23. data/lib/skeleton_loader/engine.rb +42 -0
  24. data/lib/skeleton_loader/skeleton_element_generator.rb +49 -0
  25. data/lib/skeleton_loader/template_path_finder.rb +24 -0
  26. data/lib/skeleton_loader/template_renderer.rb +41 -0
  27. data/lib/skeleton_loader/version.rb +5 -0
  28. data/lib/skeleton_loader/view_helpers.rb +19 -0
  29. data/lib/skeleton_loader.rb +36 -0
  30. data/lib/tasks/skeleton_loader_tasks.rake +23 -0
  31. metadata +91 -0
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SkeletonLoader
4
+ # Configuration class manages settings for the SkeletonLoader gem.
5
+ class Configuration
6
+ TEMPLATE_DEFAULTS = {
7
+ card: { width: 200, count: 3, per_row: 3 },
8
+ comment: { width: 900, count: 2, per_row: 1 },
9
+ default: { width: 900, count: 1, per_row: 1 },
10
+ gallery: { width: 320, count: 3, per_row: 3 },
11
+ paragraph: { width: 900, count: 1, per_row: 1 },
12
+ product: { width: 320, count: 3, per_row: 3 },
13
+ profile: { width: 320, count: 3, per_row: 3 }
14
+ }.freeze
15
+
16
+ attr_reader :scale, :template_paths, :animation_type,
17
+ :additional_allowed_tags, :additional_allowed_attributes,
18
+ :additional_allowed_css_properties, :templates
19
+
20
+ def initialize
21
+ reset!
22
+ end
23
+
24
+ # Resets all configuration options to their defaults.
25
+ def reset!
26
+ set_general_defaults
27
+ set_template_defaults
28
+ set_animation_defaults
29
+ set_security_defaults
30
+ end
31
+
32
+ def base_options
33
+ {
34
+ scale: @scale,
35
+ animation_type: @animation_type,
36
+ additional_allowed_tags: @additional_allowed_tags,
37
+ additional_allowed_attributes: @additional_allowed_attributes,
38
+ additional_allowed_css_properties: @additional_allowed_css_properties
39
+ }
40
+ end
41
+
42
+ # Returns the default options for a specific template type
43
+ def template_defaults_for(type)
44
+ @templates[type&.to_sym || :default] || @templates[:default]
45
+ end
46
+
47
+ private
48
+
49
+ def set_general_defaults
50
+ @scale = 1.0
51
+ @template_paths = []
52
+ end
53
+
54
+ def set_template_defaults
55
+ @templates = TEMPLATE_DEFAULTS.dup
56
+ end
57
+
58
+ def set_animation_defaults
59
+ @animation_type = "sl-gradient"
60
+ end
61
+
62
+ def set_security_defaults
63
+ @additional_allowed_tags = []
64
+ @additional_allowed_attributes = {}
65
+ @additional_allowed_css_properties = []
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SkeletonLoader
4
+ # SkeletonLoader::Engine integrates the SkeletonLoader gem with Rails,
5
+ # configuring asset paths, pre-compiling assets, and including view helpers
6
+ # in Action View.
7
+ class Engine < ::Rails::Engine
8
+ isolate_namespace SkeletonLoader
9
+
10
+ initializer "skeleton_loader.assets" do |app|
11
+ # CSS always through asset pipeline
12
+ app.config.assets.paths << root.join("app/assets/stylesheets")
13
+ app.config.assets.precompile += %w[skeleton_loader.css]
14
+
15
+ if defined?(Webpacker) || defined?(Shakapacker)
16
+ # You should use npm package
17
+ elsif defined?(Importmap::Engine)
18
+ gem_js_path = root.join("app/assets/javascripts").to_s
19
+ app.config.assets.paths.reject! { |path| path.to_s == gem_js_path }
20
+ app.config.assets.paths << root.join("dist")
21
+ app.config.assets.precompile += %w[skeleton_loader.js]
22
+ else
23
+ app.config.assets.paths << root.join("app/assets/javascripts")
24
+ app.config.assets.precompile += %w[skeleton_loader.js]
25
+ end
26
+ end
27
+
28
+ initializer "skeleton_loader.view_helpers" do
29
+ ActiveSupport.on_load(:action_view) { include SkeletonLoader::ViewHelpers }
30
+ end
31
+
32
+ initializer "skeleton_loader.append_routes" do |app|
33
+ app.routes.prepend do
34
+ mount SkeletonLoader::Engine, at: "/skeleton_loader", as: "skeleton_loader_engine"
35
+ end
36
+ end
37
+
38
+ initializer "skeleton_loader.append_migrations" do
39
+ config.paths["app/controllers"] << File.expand_path("../app/controllers", __dir__)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SkeletonLoader
4
+ #
5
+ # Generates skeleton loader element
6
+ #
7
+ class SkeletonElementGenerator
8
+ class << self
9
+ def generate(content_id:, options: {}, context: :view, &block)
10
+ validate_content_id!(content_id)
11
+ content = generate_content(options, &block)
12
+
13
+ css_class = context == :controller ? "skeleton-loader--client" : "skeleton-loader--server"
14
+ wrap_content(content, content_id, css_class)
15
+ end
16
+
17
+ private
18
+
19
+ def validate_content_id!(content_id)
20
+ raise SkeletonLoader::Error, "content_id is required" if content_id.blank?
21
+ end
22
+
23
+ def generate_content(options, &block)
24
+ content = if block_given?
25
+ raise Error, "Options cannot be used with a block" unless options.empty?
26
+
27
+ block.call
28
+ else
29
+ type = options[:type] || "default"
30
+ template_path = TemplatePathFinder.find(type)
31
+ TemplateRenderer.render(template_path, options)
32
+ end
33
+ # rubocop:disable Rails/OutputSafety
34
+ # NOTE: The following use of `html_safe` is intentional
35
+ content.html_safe
36
+ # rubocop:enable Rails/OutputSafety
37
+ end
38
+
39
+ def wrap_content(content, content_id, css_class)
40
+ ActionController::Base.helpers.content_tag(
41
+ :div,
42
+ content,
43
+ class: css_class,
44
+ data: { content_id: content_id }
45
+ )
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SkeletonLoader
4
+ #
5
+ # This class is responsible for locating a specific template file by type.
6
+ # It searches through configured paths and defaults to searching in
7
+ # `app/views/skeleton_loader` within the Rails root directory.
8
+ # Raises an error if the template is not found.
9
+ #
10
+ class TemplatePathFinder
11
+ def self.find(type)
12
+ template_name = "_#{type}.html.erb"
13
+ search_paths = SkeletonLoader.configuration.template_paths +
14
+ [Rails.root.join("app/views/skeleton_loader")]
15
+
16
+ search_paths.each do |path|
17
+ full_path = File.join(path, template_name)
18
+ return full_path if File.exist?(full_path)
19
+ end
20
+
21
+ raise "Template '#{template_name}' not found in any of the specified paths."
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SkeletonLoader
4
+ #
5
+ # This class handles rendering templates for skeleton loaders. It retrieves
6
+ # template files and prepares them for display as placeholders.
7
+ #
8
+ class TemplateRenderer
9
+ def self.render(template_path, options = {})
10
+ new(template_path, options).render
11
+ end
12
+
13
+ def initialize(template_path, options = {})
14
+ @template_path = template_path
15
+ @options = merge_options(options)
16
+
17
+ # Dynamically set instance variables for template rendering
18
+ @options.each do |key, value|
19
+ instance_variable_set("@#{key}", value)
20
+ end
21
+ end
22
+
23
+ def render
24
+ template_content = File.read(@template_path)
25
+ erb = ERB.new(template_content)
26
+ erb.result(binding)
27
+ rescue StandardError => e
28
+ raise "Error rendering template at #{@template_path}: #{e.message}"
29
+ end
30
+
31
+ private
32
+
33
+ def merge_options(options)
34
+ config = SkeletonLoader.configuration
35
+
36
+ config.base_options
37
+ .merge(config.template_defaults_for(options[:type]))
38
+ .merge(options)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SkeletonLoader
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SkeletonLoader
4
+ # Provides helper methods for rendering skeleton loaders in views.
5
+ module ViewHelpers
6
+ def skeleton_loader(content_id:, **options, &block)
7
+ SkeletonElementGenerator.generate(content_id: content_id, options: options, &block)
8
+ rescue StandardError => e
9
+ handle_error(e)
10
+ end
11
+
12
+ private
13
+
14
+ def handle_error(error)
15
+ Rails.logger.error "Error in skeleton_loader helper: #{error.message}"
16
+ raise
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "skeleton_loader/version"
4
+ require "skeleton_loader/configuration"
5
+ require "skeleton_loader/view_helpers"
6
+ require "skeleton_loader/template_path_finder"
7
+ require "skeleton_loader/template_renderer"
8
+ require "skeleton_loader/skeleton_element_generator"
9
+ require "skeleton_loader/engine"
10
+
11
+ require "action_view"
12
+ #
13
+ # This module serves as the entry point for the SkeletonLoader gem, which provides
14
+ # configurable skeleton loaders for Rails views. It includes configuration methods,
15
+ # custom error handling, and auto-loading for key classes and helpers.
16
+ #
17
+ # Usage:
18
+ # Configure by calling `SkeletonLoader.configure` and provide settings, such as
19
+ # template paths. SkeletonLoader provides view helpers and uses ActionView for
20
+ # generating HTML components for skeleton loaders.
21
+ #
22
+ module SkeletonLoader
23
+ class Error < StandardError; end
24
+
25
+ def self.configuration
26
+ @configuration ||= Configuration.new
27
+ end
28
+
29
+ def self.configure
30
+ yield(configuration) if block_given?
31
+ end
32
+
33
+ def self.reset
34
+ @configuration = Configuration.new
35
+ end
36
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :skeleton_loader do
4
+ desc "Build JavaScript for all targets"
5
+ task build_js: :environment do
6
+ # Run webpack build
7
+ system("yarn build")
8
+
9
+ # Ensure assets/javascripts exists
10
+ FileUtils.mkdir_p("app/assets/javascripts")
11
+
12
+ # Copy webpack build to asset pipeline
13
+ FileUtils.cp(
14
+ "dist/skeleton-loader.js",
15
+ "app/assets/javascripts/skeleton_loader.js"
16
+ )
17
+
18
+ puts "✓ Built successfully!"
19
+ puts " → Source: app/javascript/"
20
+ puts " → NPM build: dist/skeleton-loader.js"
21
+ puts " → Asset Pipeline: app/assets/javascripts/skeleton_loader.js"
22
+ end
23
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: skeleton-loader
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Emad Rahimi
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-12-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 5.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 5.0.0
27
+ description: Provides customizable, responsive skeleton loaders for Rails views.
28
+ email:
29
+ - 121079771+ersync@users.noreply.github.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - LICENSE.txt
35
+ - README.md
36
+ - app/assets/javascripts/skeleton_loader.js
37
+ - app/assets/javascripts/skeleton_loader.js.LICENSE.txt
38
+ - app/assets/stylesheets/skeleton_loader.css
39
+ - app/controllers/skeleton_loader/skeleton_loader_controller.rb
40
+ - app/javascript/client_skeleton_loader.js
41
+ - app/javascript/server_skeleton_loader.js
42
+ - app/javascript/skeleton_loader.js
43
+ - config/routes.rb
44
+ - lib/generators/skeleton_loader/add_templates_generator.rb
45
+ - lib/generators/skeleton_loader/reset_templates_generator.rb
46
+ - lib/generators/skeleton_loader/templates/_card.html.erb
47
+ - lib/generators/skeleton_loader/templates/_comment.html.erb
48
+ - lib/generators/skeleton_loader/templates/_default.html.erb
49
+ - lib/generators/skeleton_loader/templates/_gallery.html.erb
50
+ - lib/generators/skeleton_loader/templates/_paragraph.html.erb
51
+ - lib/generators/skeleton_loader/templates/_product.html.erb
52
+ - lib/generators/skeleton_loader/templates/_profile.html.erb
53
+ - lib/skeleton-loader.rb
54
+ - lib/skeleton_loader.rb
55
+ - lib/skeleton_loader/configuration.rb
56
+ - lib/skeleton_loader/engine.rb
57
+ - lib/skeleton_loader/skeleton_element_generator.rb
58
+ - lib/skeleton_loader/template_path_finder.rb
59
+ - lib/skeleton_loader/template_renderer.rb
60
+ - lib/skeleton_loader/version.rb
61
+ - lib/skeleton_loader/view_helpers.rb
62
+ - lib/tasks/skeleton_loader_tasks.rake
63
+ homepage: https://github.com/ersync/skeleton-loader
64
+ licenses:
65
+ - MIT
66
+ metadata:
67
+ allowed_push_host: https://rubygems.org
68
+ homepage_uri: https://github.com/ersync/skeleton-loader
69
+ source_code_uri: https://github.com/ersync/skeleton-loader
70
+ changelog_uri: https://github.com/ersync/skeleton-loader/blob/main/CHANGELOG.md
71
+ rubygems_mfa_required: 'true'
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: 2.5.0
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubygems_version: 3.1.6
88
+ signing_key:
89
+ specification_version: 4
90
+ summary: A Ruby on Rails gem for skeleton loading screens.
91
+ test_files: []