redmineflux_icon_compat 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 272232d401404eec7346af84c3fe7352c41f904b4292967462fab4f29daf7a89
4
+ data.tar.gz: b0775447faafc0ad28d5365a4190355fb79956e7c82bec3a114a4c04c2f4f718
5
+ SHA512:
6
+ metadata.gz: d4e9e4a3dfde1fa90da197690a5456b52f4ae8ad17fa2e0cfb5cd9fe25b96fe0773ff7c47a6912f1b0e042beab14c9a990f3718046deabcfbc88726f0c9ab55c
7
+ data.tar.gz: e50cf452bdc430577ddc4b7bdc579439912dcbfd214dfdbace58d68fceea42e8883d38bd92fd5970e4d79e9b600dabbb301742a87bd51c3ddf1ec932cb6d4893
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Redmineflux
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,105 @@
1
+ # Redmineflux Icon Compat
2
+
3
+ Compatibility helper gem for Redmine plugin icons.
4
+
5
+ This gem gives one helper API (`rf_icon_link`) that works in both:
6
+ - Redmine 5 style icons (`icon icon-*` classes)
7
+ - Redmine 6 SVG sprite icons (`sprite_icon`)
8
+
9
+ ## Usage in a Redmine plugin
10
+
11
+ 1. Add to plugin Gemfile:
12
+
13
+ ```ruby
14
+ gem 'redmineflux_icon_compat', path: '../redmineflux_icon_compat'
15
+ ```
16
+
17
+ 2. Include helper where needed:
18
+
19
+ ```ruby
20
+ include RedminefluxIconCompat::Helper
21
+ ```
22
+
23
+ 3. Use in views/helpers:
24
+
25
+ ```ruby
26
+ rf_icon_link(:add, 'Add', '#')
27
+ ```
28
+
29
+ ## Run Tests
30
+
31
+ From Redmine root:
32
+
33
+ ```bash
34
+ ruby plugins/redmineflux_icon_compat/test/helper_test.rb
35
+ ```
36
+
37
+ Or from gem directory:
38
+
39
+ ```bash
40
+ cd plugins/redmineflux_icon_compat
41
+ ruby test/helper_test.rb
42
+ ```
43
+
44
+ ## Release Workflow (RubyGems)
45
+
46
+ 1. Create RubyGems account: https://rubygems.org/sign_up
47
+ 2. Login from terminal:
48
+
49
+ ```bash
50
+ gem signin
51
+ ```
52
+
53
+ 3. Bump version in:
54
+ - `plugins/redmineflux_icon_compat/lib/redmineflux_icon_compat/version.rb`
55
+
56
+ 4. Run tests:
57
+
58
+ ```bash
59
+ ruby plugins/redmineflux_icon_compat/test/helper_test.rb
60
+ ```
61
+
62
+ 5. Build the gem:
63
+
64
+ ```bash
65
+ cd plugins/redmineflux_icon_compat
66
+ gem build redmineflux_icon_compat.gemspec
67
+ ```
68
+
69
+ 6. Push to RubyGems:
70
+
71
+ ```bash
72
+ gem push redmineflux_icon_compat-<VERSION>.gem
73
+ ```
74
+
75
+ 7. Verify:
76
+ - Open `https://rubygems.org/gems/redmineflux_icon_compat`
77
+ - Install test:
78
+
79
+ ```bash
80
+ gem install redmineflux_icon_compat
81
+ ```
82
+
83
+ ## Ownership and Security (Recommended)
84
+
85
+ Add backup owners:
86
+
87
+ ```bash
88
+ gem owner redmineflux_icon_compat --add teammate@example.com
89
+ ```
90
+
91
+ Require MFA on RubyGems account for push/yank.
92
+
93
+ ## Consume Published Gem
94
+
95
+ In plugin `Gemfile`:
96
+
97
+ ```ruby
98
+ gem 'redmineflux_icon_compat', '~> 0.1.0'
99
+ ```
100
+
101
+ Then:
102
+
103
+ ```bash
104
+ bundle install
105
+ ```
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RedminefluxIconCompat
4
+ module Helper
5
+ RF_ICON_MAP = {
6
+ delete: { legacy: 'del', sprite: 'del' },
7
+ add: { legacy: 'add', sprite: 'add' },
8
+ edit: { legacy: 'edit', sprite: 'edit' },
9
+ copy: { legacy: 'copy', sprite: 'copy' },
10
+ save: { legacy: 'save', sprite: 'save' }
11
+ }.freeze
12
+
13
+ # Centralized icon-link renderer for Redmine 5/6 compatibility.
14
+ def rf_icon_link(icon, label, href = '#', html_options = {})
15
+ icon_names = rf_icon_names(icon)
16
+ options = (html_options || {}).dup
17
+ use_sprite = rf_sprite_icons_available?
18
+ options[:class] = rf_icon_classes(options[:class], icon_names[:legacy], use_sprite)
19
+
20
+ content = if use_sprite
21
+ rf_sprite_icon_markup(icon_names[:sprite], label)
22
+ else
23
+ label
24
+ end
25
+
26
+ link_to(content, href, options)
27
+ end
28
+
29
+ # Redmine 6+ provides sprite icons through IconsHelper#sprite_icon.
30
+ def rf_sprite_icons_available?
31
+ respond_to?(:sprite_icon, true) || rf_global_sprite_helper_available?
32
+ end
33
+
34
+ private
35
+
36
+ def rf_sprite_icon_markup(icon_name, label)
37
+ if respond_to?(:sprite_icon, true)
38
+ sprite_icon(icon_name, label)
39
+ elsif rf_global_sprite_helper_available?
40
+ ApplicationController.helpers.sprite_icon(icon_name, label)
41
+ else
42
+ label
43
+ end
44
+ end
45
+
46
+ def rf_global_sprite_helper_available?
47
+ defined?(ApplicationController) &&
48
+ ApplicationController.respond_to?(:helpers) &&
49
+ ApplicationController.helpers.respond_to?(:sprite_icon)
50
+ end
51
+
52
+ def rf_icon_names(icon)
53
+ key = icon.to_sym
54
+ RF_ICON_MAP.fetch(key) do
55
+ name = key.to_s.tr('_', '-')
56
+ { legacy: name, sprite: name }
57
+ end
58
+ end
59
+
60
+ def rf_icon_classes(existing_classes, legacy_icon_name, use_sprite)
61
+ classes = ['rf-icon-link', 'icon']
62
+ if use_sprite
63
+ classes << 'rf-icon-sprite'
64
+ else
65
+ classes << "icon-#{legacy_icon_name}"
66
+ end
67
+ classes.concat(existing_classes.to_s.split(/\s+/)) if existing_classes.respond_to?(:present?) ? existing_classes.present? : !existing_classes.to_s.empty?
68
+ classes.uniq.join(' ')
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RedminefluxIconCompat
4
+ class Railtie < Rails::Railtie
5
+ config.to_prepare do
6
+ helper_mod = RedminefluxIconCompat::Helper
7
+
8
+ if defined?(ApplicationHelper) && !ApplicationHelper.included_modules.include?(helper_mod)
9
+ ApplicationHelper.send(:include, helper_mod)
10
+ end
11
+
12
+ if defined?(ActionController::Base)
13
+ ActionController::Base.helper helper_mod
14
+ end
15
+
16
+ if defined?(ActionView::Base) && !ActionView::Base.included_modules.include?(helper_mod)
17
+ ActionView::Base.send(:include, helper_mod)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RedminefluxIconCompat
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'redmineflux_icon_compat/version'
4
+ require_relative 'redmineflux_icon_compat/helper'
5
+ require_relative 'redmineflux_icon_compat/railtie' if defined?(Rails::Railtie)
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'test_helper'
4
+
5
+ class RedminefluxIconCompatHelperTest < Minitest::Test
6
+ class DummyView
7
+ include RedminefluxIconCompat::Helper
8
+
9
+ def link_to(content, href, options = {})
10
+ css = options[:class].to_s
11
+ %(<a class="#{css}" href="#{href}">#{content}</a>)
12
+ end
13
+ end
14
+
15
+ class SpriteView < DummyView
16
+ def sprite_icon(icon_name, label)
17
+ %(<svg class="icon-svg" data-icon="#{icon_name}"></svg><span class="icon-label">#{label}</span>)
18
+ end
19
+ end
20
+
21
+ def teardown
22
+ if Object.const_defined?(:ApplicationController)
23
+ Object.send(:remove_const, :ApplicationController)
24
+ end
25
+ end
26
+
27
+ def test_legacy_mode_uses_icon_classes_when_sprite_not_available
28
+ view = DummyView.new
29
+
30
+ html = view.rf_icon_link(:add, 'Add', '/path')
31
+
32
+ assert_includes html, 'icon-add'
33
+ refute_includes html, 'rf-icon-sprite'
34
+ refute_includes html, 'icon-svg'
35
+ end
36
+
37
+ def test_local_sprite_icon_is_used_when_available
38
+ view = SpriteView.new
39
+
40
+ html = view.rf_icon_link(:edit, 'Edit', '/edit')
41
+
42
+ assert_includes html, 'rf-icon-sprite'
43
+ assert_includes html, 'icon-svg'
44
+ refute_includes html, 'icon-edit'
45
+ end
46
+
47
+ def test_global_sprite_helper_is_used_when_local_helper_missing
48
+ app_helpers = Object.new
49
+ def app_helpers.sprite_icon(icon_name, label)
50
+ %(<svg class="icon-svg" data-icon="#{icon_name}"></svg><span class="icon-label">#{label}</span>)
51
+ end
52
+
53
+ app_controller = Class.new do
54
+ define_singleton_method(:helpers) { app_helpers }
55
+ end
56
+
57
+ Object.const_set(:ApplicationController, app_controller)
58
+
59
+ view = DummyView.new
60
+ html = view.rf_icon_link(:delete, 'Delete', '/delete')
61
+
62
+ assert_includes html, 'rf-icon-sprite'
63
+ assert_includes html, 'icon-svg'
64
+ refute_includes html, 'icon-del'
65
+ end
66
+
67
+ def test_unknown_icon_uses_dashed_fallback_name
68
+ view = DummyView.new
69
+
70
+ html = view.rf_icon_link(:calendar_today, 'Calendar', '/calendar')
71
+
72
+ assert_includes html, 'icon-calendar-today'
73
+ end
74
+
75
+ def test_existing_classes_are_preserved
76
+ view = DummyView.new
77
+
78
+ html = view.rf_icon_link(:add, 'Add', '/path', class: 'btn btn-primary')
79
+
80
+ assert_includes html, 'btn'
81
+ assert_includes html, 'btn-primary'
82
+ assert_includes html, 'rf-icon-link'
83
+ end
84
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest/autorun'
4
+ require 'ostruct'
5
+ require_relative '../lib/redmineflux_icon_compat'
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redmineflux_icon_compat
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Redmineflux
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-04-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: actionview
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: railties
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Provides helper methods to render icon links compatible with Redmine
42
+ 5 legacy icon classes and Redmine 6 sprite icons.
43
+ email:
44
+ - support@redmineflux.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - LICENSE.txt
50
+ - README.md
51
+ - lib/redmineflux_icon_compat.rb
52
+ - lib/redmineflux_icon_compat/helper.rb
53
+ - lib/redmineflux_icon_compat/railtie.rb
54
+ - lib/redmineflux_icon_compat/version.rb
55
+ - test/helper_test.rb
56
+ - test/test_helper.rb
57
+ homepage: https://www.redmineflux.com
58
+ licenses:
59
+ - MIT
60
+ metadata: {}
61
+ post_install_message:
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '3.0'
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubygems_version: 3.4.20
77
+ signing_key:
78
+ specification_version: 4
79
+ summary: Icon compatibility helpers for Redmine 5 and 6 plugins
80
+ test_files: []