fontawesome_subsetter 0.1.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8d07501e79546fbe88ff5c7130cb5b0a5e90c2bc0dedc50bebf97989a966cf33
4
+ data.tar.gz: cbbd58e800778f1098353a673cbf11348b656cc13d9b832c5b53980dbb588ab9
5
+ SHA512:
6
+ metadata.gz: d5dbc3c8c0109591d830a15f7828c4976239443bada05930b15d2c99a70a45159cd80c68b080c17665db2f6798cfc8739622dd62980436c138ad19c90d5bc1ef
7
+ data.tar.gz: 64d4f1265db3642169657c29008917a462ba0cec6bd92113766a109df9ebb7afcdd79c3c25f2253f2d1f4337f97a5af86216722f2aa6026d266d5ec57bfe8e58
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,113 @@
1
+ # FontAwesome Subsetter
2
+
3
+ A Rails gem that tree-shakes FontAwesome — scans your views and helpers for `icon()` calls, subsets WOFF2 font files to include only used glyphs, and generates minimal CSS.
4
+
5
+ ## Requirements
6
+
7
+ - **FontAwesome** files in `vendor/fontawesome/` (metadata, scss, webfonts)
8
+ - **pyftsubset** (from [fonttools](https://github.com/fonttools/fonttools)): `pip install fonttools brotli`
9
+ - **sass-embedded** gem for SCSS compilation
10
+
11
+ ## Installation
12
+
13
+ Add to your Gemfile:
14
+
15
+ ```ruby
16
+ gem "fontawesome_subsetter"
17
+ ```
18
+
19
+ Then run `bundle install`.
20
+
21
+ ## Setup
22
+
23
+ ### Directory Structure
24
+
25
+ The gem expects FontAwesome Pro files in your project at:
26
+
27
+ ```
28
+ vendor/
29
+ fontawesome/
30
+ metadata/
31
+ icons.yml
32
+ scss/
33
+ variables.scss
34
+ functions.scss
35
+ mixins.scss
36
+ core.scss
37
+ animated.scss
38
+ icons.scss
39
+ solid.scss
40
+ regular.scss
41
+ ...
42
+ webfonts/
43
+ fa-solid-900.woff2
44
+ fa-regular-400.woff2
45
+ fa-brands-400.woff2
46
+ fa-duotone-900.woff2
47
+ fa-thin-100.woff2
48
+ ```
49
+
50
+ > **Note:** In `vendor/fontawesome/scss/variables.scss`, change `$icons` and `$brand-icons` to empty maps with `!default` so the subsetter can inject only the used icons.
51
+
52
+ ## Features
53
+
54
+ ### 1. Icon Helper
55
+
56
+ The gem provides an `icon` helper available in all views:
57
+
58
+ ```slim
59
+ = icon(:fas, :download, "Download", class: "mr-1")
60
+ = icon(:far, :check)
61
+ = icon(:fab, :github)
62
+ ```
63
+
64
+ ### 2. Puma Plugin (Development Watch Mode)
65
+
66
+ Add to your `config/puma.rb`:
67
+
68
+ ```ruby
69
+ if ENV.fetch("RAILS_ENV", "development") == "development"
70
+ plugin :fontawesome
71
+ end
72
+ ```
73
+
74
+ This watches `app/views/`, `app/helpers/`, and `app/components/` for changes and automatically rebuilds subsetted fonts.
75
+
76
+ ### 3. Rake Task (Deploy)
77
+
78
+ The gem automatically hooks into `assets:precompile`:
79
+
80
+ ```bash
81
+ rake assets:precompile # fontawesome:subset runs first
82
+ ```
83
+
84
+ You can also run it manually:
85
+
86
+ ```bash
87
+ rake fontawesome:subset
88
+ ```
89
+
90
+ ## Configuration
91
+
92
+ ```ruby
93
+ # config/initializers/fontawesome_subsetter.rb
94
+ FontawesomeSubsetter.configure do | config |
95
+ # Paths to scan for icon() calls (defaults shown)
96
+ config.scan_globs = ["app/views/**/*.slim", "app/helpers/**/*.rb"]
97
+
98
+ # Regex to match icon() calls (default shown)
99
+ config.icon_regex = /icon\(\s*:(?<prefix>fas|far|fab|fad|fal|fat)\s*,\s*:(?<icon>[\w_\-]+)\b/
100
+
101
+ # Override default paths (optional — defaults use Rails.root)
102
+ # config.meta_path = Rails.root.join("vendor", "fontawesome", "metadata", "icons.yml")
103
+ # config.fonts_dir = Rails.root.join("vendor", "fontawesome", "webfonts")
104
+ # config.build_dir = Rails.root.join("app", "assets", "builds")
105
+
106
+ # Custom SCSS template (optional — receives @styles hash, must return SCSS string)
107
+ # config.scss_template = ->(styles) { "..." }
108
+ end
109
+ ```
110
+
111
+ ## License
112
+
113
+ [MIT](LICENSE.txt) — Copyright (c) 2026
@@ -0,0 +1,17 @@
1
+ module FontawesomeSubsetter
2
+
3
+ class Engine < ::Rails::Engine
4
+
5
+ initializer "fontawesome_subsetter.helpers" do
6
+ ActiveSupport.on_load(:action_view) do
7
+ include FontawesomeSubsetter::IconHelper
8
+ end
9
+ end
10
+
11
+ rake_tasks do
12
+ load File.expand_path("../tasks/fontawesome_subsetter.rake", __dir__)
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,21 @@
1
+ module FontawesomeSubsetter
2
+
3
+ module IconHelper
4
+
5
+ def icon(style, name, text = nil, html_options = {}, &block)
6
+ text, html_options = nil, text if text.is_a?(Hash)
7
+
8
+ html_options[:class] = "#{ style } fa-#{ name.to_s.dasherize }#{ " #{ html_options[:class] }" if html_options.key? :class }"
9
+
10
+ html = content_tag :i, nil, html_options
11
+
12
+ html = "#{ html } #{ text }" if text.present?
13
+
14
+ html = "#{ html } #{ capture block }" if block_given?
15
+
16
+ html.html_safe
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,210 @@
1
+ require "json"
2
+ require "open3"
3
+ require "fileutils"
4
+ require "yaml"
5
+ require "set"
6
+
7
+ module FontawesomeSubsetter
8
+
9
+ class Subsetter
10
+
11
+ def initialize(root: nil)
12
+ @file_icon_map = {}
13
+ @root = root || defined?(Rails) && Rails.root || Pathname.new(Dir.pwd)
14
+ @root = Pathname.new(@root) unless @root.is_a?(Pathname)
15
+
16
+ config = FontawesomeSubsetter.configuration
17
+
18
+ @meta_path = config.meta_path || @root.join("vendor", "fontawesome", "metadata", "icons.yml")
19
+ @fonts_dir = config.fonts_dir || @root.join("vendor", "fontawesome", "webfonts")
20
+ @build_dir = config.build_dir || @root.join("app", "assets", "builds")
21
+ @webfonts_dir = @build_dir.join("webfonts")
22
+ @scan_globs = config.scan_globs
23
+ @icon_regex = config.icon_regex
24
+
25
+ @styles = {
26
+ "solid" => { name: "solid", prefix: "fas", unicode_cache: Set.new, icon_cache: Set.new, sass_icon_cache: Set.new, changed: false, file: "fa-solid-900.woff2" },
27
+ "regular" => { name: "regular", prefix: "far", unicode_cache: Set.new, icon_cache: Set.new, sass_icon_cache: Set.new, changed: false, file: "fa-regular-400.woff2" },
28
+ "light" => { name: "light", prefix: "fal", unicode_cache: Set.new, icon_cache: Set.new, sass_icon_cache: Set.new, changed: false, file: "fa-thin-100.woff2" },
29
+ "thin" => { name: "thin", prefix: "fat", unicode_cache: Set.new, icon_cache: Set.new, sass_icon_cache: Set.new, changed: false, file: "fa-thin-100.woff2" },
30
+ "duotone" => { name: "duotone", prefix: "fad", unicode_cache: Set.new, icon_cache: Set.new, sass_icon_cache: Set.new, changed: false, file: "fa-duotone-900.woff2" },
31
+ "brands" => { name: "brands", prefix: "fab", unicode_cache: Set.new, icon_cache: Set.new, sass_icon_cache: Set.new, changed: false, file: "fa-brands-400.woff2" }
32
+ }
33
+
34
+ @watch_paths = [
35
+ @root.join("app", "views"),
36
+ @root.join("app", "helpers"),
37
+ @root.join("app", "components")
38
+ ].select(&:exist?)
39
+
40
+ @watch_file_type_regex = config.watch_file_type_regex
41
+
42
+ FileUtils.rm_rf(@webfonts_dir)
43
+ FileUtils.mkdir_p(@webfonts_dir)
44
+
45
+ # Load FontAwesome metadata
46
+ @metadata = YAML.safe_load(File.read(@meta_path))
47
+
48
+ # Build unicode map, set entry to an array of all codepoints (main + secondary)
49
+ @metadata.each { | key, entry | @metadata[key]["unicodes"] = Set.new([ "U+#{ entry['unicode'].upcase }", *entry.dig("aliases", "unicodes", "secondary")&.map { | s | "U+#{ s.upcase }" } ]) }
50
+
51
+ # Build alias map
52
+ @metadata.merge!(@metadata.values.flat_map { | entry | (entry.dig("aliases", "names") || []).map { [ it, entry ] } }.to_h)
53
+
54
+ # Strip useless metadata
55
+ @metadata.each_value { it.except!("changes", "label", "voted", "search", "styles", "aliases") }
56
+ end
57
+
58
+ # Updates the cache for each style, returns the styles that have changed.
59
+ def scan_files_and_update_caches(files)
60
+ files.each do | path |
61
+
62
+ text = File.read(path)
63
+ text.scan(@icon_regex).each do | prefix, icon |
64
+
65
+ style = @styles.find { it&.last[:prefix] == prefix }&.last
66
+ next unless style
67
+
68
+ normalized = icon.tr("_", "-")
69
+ entry = @metadata[normalized]
70
+ next unless entry
71
+
72
+ # If the icon is new for this style, update the caches
73
+ if style[:icon_cache].add?(normalized)
74
+ style[:unicode_cache].merge(entry["unicodes"])
75
+ style[:sass_icon_cache].add("\"#{ normalized }\": \\#{ entry['unicode'] }")
76
+ style[:changed] = true
77
+ else
78
+ nil
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+ end
85
+
86
+ # Takes an array of styles and creates a thread to subset each font file
87
+ def subset_webfonts(styles)
88
+ styles.map { | style | Thread.new(style) { subset_font(style) } }.each(&:join)
89
+ end
90
+
91
+ def subset_font(style)
92
+ file = style[:file]
93
+ out_file = @webfonts_dir.join(file)
94
+ cmd = "pyftsubset #{ @fonts_dir.join(file) } --flavor=woff2 --unicodes=#{ style[:unicode_cache].to_a.join(",") } --output-file=#{ out_file } --layout-features=* --no-hinting"
95
+
96
+ puts "[FontSubsetter][#{ style[:name] }] #{ cmd }"
97
+ stdout, stderr, status = Open3.capture3(cmd)
98
+ if status.success?
99
+ puts "[FontSubsetter][#{ style[:name] }] wrote #{ out_file }"
100
+ else
101
+ warn "[FontSubsetter][#{ style[:name] }] subset failed:\n#{ stderr }"
102
+ raise "pyftsubset failed (exit #{ status.exitstatus })"
103
+ end
104
+ end
105
+
106
+ def subset_stylesheets
107
+ styles = @styles.values.select { it[:sass_icon_cache].any? }
108
+
109
+ scss_template = FontawesomeSubsetter.configuration.scss_template
110
+
111
+ scss_string = if scss_template
112
+ scss_template.call(@styles)
113
+ else
114
+ default_scss_template(styles)
115
+ end
116
+
117
+ # Compile the dynamic SCSS. `load_paths` tells Sass where to find the imported files.
118
+ compiled_css = Sass.compile_string(scss_string, style: :compressed, load_paths: [ @root ]).css
119
+
120
+ # Forcefully remove all comments, including "loud" /*! ... */ comments for licenses.
121
+ compiled_css = compiled_css.gsub(/\/\*!.*?\*\//m, "")
122
+
123
+ # Output to builds folder, which is the standard for Propshaft
124
+ out_file = @build_dir.join("fontawesome.css")
125
+ File.write(out_file, compiled_css)
126
+ puts "[FontSubsetter] wrote #{ out_file } with styles: #{ styles.map { it[:name] }.join(', ') }"
127
+ end
128
+
129
+ def build(files_to_scan = nil)
130
+ files_to_scan ||= @scan_globs.flat_map { Dir.glob it }
131
+
132
+ scan_files_and_update_caches(files_to_scan)
133
+
134
+ styles = @styles.values.select { it[:changed] }
135
+
136
+ # Rebuild assets only if caches have changed
137
+ unless styles.empty?
138
+ subset_webfonts(styles)
139
+ subset_stylesheets
140
+ @styles.values.each { it[:changed] = false }
141
+ end
142
+ end
143
+
144
+ def build_watch
145
+ require "listen"
146
+
147
+ # Initial full scan and build
148
+ build()
149
+
150
+ puts "Starting FontAwesome watch mode..."
151
+
152
+ listener = Listen.to(*@watch_paths) do | modified, added, removed |
153
+
154
+ # NOTE: At most, it seems to take around 1.7 seconds to subset
155
+ start_time = Time.now
156
+
157
+ puts "Detected changes: modified=#{ modified }, added=#{ added }, removed=#{ removed }"
158
+
159
+ # Scan only modified and added files
160
+ build(modified + added)
161
+
162
+ elapsed = Time.now - start_time
163
+ puts "[FontSubsetter] Total subsetting time: #{ format('%.2f', elapsed) } seconds"
164
+
165
+ end
166
+
167
+ listener.start
168
+
169
+ # Keep the process alive
170
+ loop do
171
+
172
+ sleep 1
173
+
174
+ end
175
+ rescue Interrupt
176
+ puts "FontAwesome watch stopped"
177
+ listener&.stop
178
+ end
179
+
180
+ private
181
+
182
+ def default_scss_template(styles)
183
+ <<-SCSS
184
+
185
+ // NOTE: $icons and $brand-icons were changed in variables to just be empty arrays with !default.
186
+ @use "./vendor/fontawesome/scss/variables" with (
187
+ $font-path: "webfonts",
188
+ $icons: (#{ @styles.except("brands").values.reduce(Set.new) { | all_icons, style | all_icons.merge(style[:sass_icon_cache]) }.join(", ") }),
189
+ $brand-icons: (#{ @styles["brands"][:sass_icon_cache].to_a.join(", ") }));
190
+
191
+ @use "./vendor/fontawesome/scss/functions";
192
+ @use "./vendor/fontawesome/scss/mixins";
193
+ @use "./vendor/fontawesome/scss/core";
194
+ // @use "./vendor/fontawesome/scss/sizing";
195
+ // @use "./vendor/fontawesome/scss/widths";
196
+ // @use "./vendor/fontawesome/scss/list";
197
+ // @use "./vendor/fontawesome/scss/bordered";
198
+ @use "./vendor/fontawesome/scss/animated";
199
+ // @use "./vendor/fontawesome/scss/rotated-flipped";
200
+ // @use "./vendor/fontawesome/scss/stacked";
201
+ @use "./vendor/fontawesome/scss/icons";
202
+
203
+ #{ styles.map { "@use \"./vendor/fontawesome/scss/#{ it[:name] }.scss\";" }.join("\n") }
204
+
205
+ SCSS
206
+ end
207
+
208
+ end
209
+
210
+ end
@@ -0,0 +1,5 @@
1
+ module FontawesomeSubsetter
2
+
3
+ VERSION = "0.1.1"
4
+
5
+ end
@@ -0,0 +1,35 @@
1
+ require_relative "fontawesome_subsetter/version"
2
+ require_relative "fontawesome_subsetter/icon_helper"
3
+ require_relative "fontawesome_subsetter/subsetter"
4
+ require_relative "fontawesome_subsetter/engine" if defined?(Rails)
5
+
6
+ module FontawesomeSubsetter
7
+
8
+ class << self
9
+
10
+ attr_writer :configuration
11
+
12
+ def configuration
13
+ @configuration ||= Configuration.new
14
+ end
15
+
16
+ def configure
17
+ yield(configuration)
18
+ end
19
+
20
+ end
21
+
22
+ class Configuration
23
+
24
+ attr_accessor :meta_path, :fonts_dir, :build_dir, :scan_globs, :watch_paths,
25
+ :watch_file_type_regex, :icon_regex, :scss_template, :styles
26
+
27
+ def initialize
28
+ @scan_globs = ["app/views/**/*.slim", "app/helpers/**/*.rb"]
29
+ @watch_file_type_regex = /\.(slim|rb)$/
30
+ @icon_regex = /icon\(\s*:(?<prefix>fas|far|fab|fad|fal|fat)\s*,\s*:(?<icon>[\w_\-]+)\b/
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,93 @@
1
+ require "puma/plugin"
2
+
3
+ class Fontawesome
4
+ end
5
+
6
+ Puma::Plugin.create do
7
+
8
+ attr_reader :puma_pid, :fontawesome_pid, :log_writer
9
+
10
+ def start(launcher)
11
+ @log_writer = launcher.log_writer
12
+ @puma_pid = $PROCESS_ID
13
+
14
+ launcher.events.on_booted do
15
+
16
+ @fontawesome_pid = fork do
17
+
18
+ Thread.new { monitor_puma }
19
+
20
+ begin
21
+ # Set up signal handling for clean shutdown
22
+ trap("INT") { exit 0 }
23
+ trap("TERM") { exit 0 }
24
+
25
+ require "fontawesome_subsetter"
26
+ subsetter = FontawesomeSubsetter::Subsetter.new
27
+ subsetter.build_watch
28
+ rescue => e
29
+ @log_writer.log "FontAwesome subsetter error: #{ e.message }"
30
+ @log_writer.log e.backtrace.join("\n")
31
+ exit 1
32
+ end
33
+
34
+ end
35
+
36
+ in_background do
37
+
38
+ monitor_fontawesome
39
+
40
+ end
41
+
42
+ end
43
+
44
+ launcher.events.on_stopped { stop_fontawesome }
45
+ end
46
+
47
+ private
48
+
49
+ def stop_fontawesome
50
+ Process.waitpid(fontawesome_pid, Process::WNOHANG)
51
+ log "Stopping FontAwesome..."
52
+ Process.kill(:INT, fontawesome_pid) if fontawesome_pid
53
+ Process.wait(fontawesome_pid)
54
+ rescue Errno::ECHILD, Errno::ESRCH
55
+ end
56
+
57
+ def monitor_puma
58
+ monitor(:puma_dead?, "Detected Puma has gone away, stopping FontAwesome...")
59
+ end
60
+
61
+ def monitor_fontawesome
62
+ monitor(:fontawesome_dead?, "Detected FontAwesome has gone away, stopping Puma...")
63
+ end
64
+
65
+ def monitor(process_dead, message)
66
+ loop do
67
+
68
+ if send(process_dead)
69
+ log message
70
+ Process.kill(:INT, $PROCESS_ID)
71
+ break
72
+ end
73
+ sleep 2
74
+
75
+ end
76
+ end
77
+
78
+ def fontawesome_dead?
79
+ Process.waitpid(fontawesome_pid, Process::WNOHANG)
80
+ false
81
+ rescue Errno::ECHILD, Errno::ESRCH
82
+ true
83
+ end
84
+
85
+ def puma_dead?
86
+ Process.ppid != puma_pid
87
+ end
88
+
89
+ def log(...)
90
+ log_writer.log(...)
91
+ end
92
+
93
+ end
@@ -0,0 +1,15 @@
1
+ namespace :fontawesome do
2
+
3
+ desc "Build FontAwesome, subsetting icons and shaking out unused CSS."
4
+ task :subset do
5
+ require "fontawesome_subsetter"
6
+
7
+ subsetter = FontawesomeSubsetter::Subsetter.new
8
+ subsetter.build()
9
+
10
+ puts "FontAwesome subset build completed successfully!"
11
+ end
12
+
13
+ end
14
+
15
+ Rake::Task["assets:precompile"].enhance(["fontawesome:subset"])
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fontawesome_subsetter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - 16554289+optimuspwnius@users.noreply.github.com
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: railties
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '7.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '7.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: actionview
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '7.0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '7.0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: sass-embedded
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '1.0'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '1.0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: listen
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '3.0'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '3.0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: puma
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '5.0'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '5.0'
82
+ description: Scans your views and helpers for icon() calls, subsets FontAwesome Pro
83
+ WOFF2 fonts via pyftsubset, and generates minimal CSS. Includes a Puma plugin for
84
+ development watch mode, a Rails view helper, and a rake task that hooks into assets:precompile.
85
+ email:
86
+ - 16554289+optimuspwnius@users.noreply.github.com
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - LICENSE.txt
92
+ - README.md
93
+ - lib/fontawesome_subsetter.rb
94
+ - lib/fontawesome_subsetter/engine.rb
95
+ - lib/fontawesome_subsetter/icon_helper.rb
96
+ - lib/fontawesome_subsetter/subsetter.rb
97
+ - lib/fontawesome_subsetter/version.rb
98
+ - lib/puma/plugin/fontawesome.rb
99
+ - lib/tasks/fontawesome_subsetter.rake
100
+ homepage: https://github.com/optimuspwnius/fontawesome-subsetter
101
+ licenses:
102
+ - MIT
103
+ metadata:
104
+ homepage_uri: https://github.com/optimuspwnius/fontawesome-subsetter
105
+ source_code_uri: https://github.com/optimuspwnius/fontawesome-subsetter
106
+ changelog_uri: https://github.com/optimuspwnius/fontawesome-subsetter/blob/main/CHANGELOG.md
107
+ allowed_push_host: https://rubygems.org
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '3.2'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubygems_version: 4.0.7
123
+ specification_version: 4
124
+ summary: FontAwesome Pro subsetter for Rails — tree-shakes unused icons from font
125
+ files and CSS.
126
+ test_files: []