skeleton-loader 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +401 -0
- data/app/assets/javascripts/skeleton_loader.js +2 -0
- data/app/assets/javascripts/skeleton_loader.js.LICENSE.txt +1 -0
- data/app/assets/stylesheets/skeleton_loader.css +83 -0
- data/app/controllers/skeleton_loader/skeleton_loader_controller.rb +60 -0
- data/app/javascript/client_skeleton_loader.js +234 -0
- data/app/javascript/server_skeleton_loader.js +113 -0
- data/app/javascript/skeleton_loader.js +6 -0
- data/config/routes.rb +5 -0
- data/lib/generators/skeleton_loader/add_templates_generator.rb +16 -0
- data/lib/generators/skeleton_loader/reset_templates_generator.rb +16 -0
- data/lib/generators/skeleton_loader/templates/_card.html.erb +31 -0
- data/lib/generators/skeleton_loader/templates/_comment.html.erb +61 -0
- data/lib/generators/skeleton_loader/templates/_default.html.erb +23 -0
- data/lib/generators/skeleton_loader/templates/_gallery.html.erb +19 -0
- data/lib/generators/skeleton_loader/templates/_paragraph.html.erb +28 -0
- data/lib/generators/skeleton_loader/templates/_product.html.erb +49 -0
- data/lib/generators/skeleton_loader/templates/_profile.html.erb +28 -0
- data/lib/skeleton-loader.rb +7 -0
- data/lib/skeleton_loader/configuration.rb +68 -0
- data/lib/skeleton_loader/engine.rb +42 -0
- data/lib/skeleton_loader/skeleton_element_generator.rb +49 -0
- data/lib/skeleton_loader/template_path_finder.rb +24 -0
- data/lib/skeleton_loader/template_renderer.rb +41 -0
- data/lib/skeleton_loader/version.rb +5 -0
- data/lib/skeleton_loader/view_helpers.rb +19 -0
- data/lib/skeleton_loader.rb +36 -0
- data/lib/tasks/skeleton_loader_tasks.rake +23 -0
- 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,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: []
|