skeleton-loader 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []