heroicons_helper 0.5.0 → 0.7.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 +4 -4
- data/Gemfile +4 -0
- data/README.md +2 -2
- data/heroicons_helper.gemspec +6 -0
- data/lib/heroicons_helper/cache.rb +11 -3
- data/lib/heroicons_helper/data.json +1 -3682
- data/lib/heroicons_helper/icon.rb +16 -7
- data/lib/heroicons_helper/version.rb +1 -1
- data/lib/heroicons_helper.rb +4 -3
- data/package-lock.json +15 -15
- data/package.json +1 -1
- data/script/keywords.json +1 -1
- data/script/update_heroicons +19 -36
- metadata +19 -5
@@ -1,5 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "set"
|
4
|
+
require "active_support/core_ext/string/output_safety"
|
5
|
+
|
3
6
|
module HeroiconsHelper
|
4
7
|
# Icon to show heroicons by name and variant.
|
5
8
|
class Icon
|
@@ -7,15 +10,17 @@ module HeroiconsHelper
|
|
7
10
|
|
8
11
|
VARIANT_OUTLINE = "outline"
|
9
12
|
VARIANT_SOLID = "solid"
|
10
|
-
|
13
|
+
VARIANT_MINI = "mini"
|
14
|
+
VALID_VARIANTS = Set.new([VARIANT_OUTLINE, VARIANT_SOLID, VARIANT_MINI]).freeze
|
11
15
|
|
12
|
-
def initialize(name, variant, attributes: {})
|
16
|
+
def initialize(name, variant, unsafe: false, attributes: {})
|
13
17
|
@name = name.to_s
|
14
18
|
@variant = variant.to_s
|
19
|
+
@unsafe = unsafe
|
15
20
|
|
16
21
|
heroicon = get_heroicon(@name, @variant)
|
17
22
|
|
18
|
-
@path = heroicon["path"]
|
23
|
+
@path = safe? ? ActiveSupport::SafeBuffer.new(heroicon["path"]) : heroicon["path"]
|
19
24
|
@width = heroicon["width"]
|
20
25
|
@height = heroicon["height"]
|
21
26
|
@keywords = heroicon["keywords"]
|
@@ -33,6 +38,10 @@ module HeroiconsHelper
|
|
33
38
|
"<!-- Heroicon name: #{@variant}/#{@name} --><svg xmlns=\"http://www.w3.org/2000/svg\" #{html_attributes}>#{@path}</svg>"
|
34
39
|
end
|
35
40
|
|
41
|
+
private def safe?
|
42
|
+
!@unsafe
|
43
|
+
end
|
44
|
+
|
36
45
|
private def html_attributes
|
37
46
|
attrs = []
|
38
47
|
@attributes.each_pair { |attr, value| attrs << "#{attr}=\"#{value}\"" }
|
@@ -52,7 +61,7 @@ module HeroiconsHelper
|
|
52
61
|
accessible
|
53
62
|
end
|
54
63
|
|
55
|
-
# prepare the
|
64
|
+
# prepare the heroicon class
|
56
65
|
private def classes
|
57
66
|
"heroicon heroicon-#{@name}-#{@variant} #{@attributes[:class]} ".strip
|
58
67
|
end
|
@@ -64,7 +73,7 @@ module HeroiconsHelper
|
|
64
73
|
fill: "none",
|
65
74
|
stroke: "currentColor",
|
66
75
|
}
|
67
|
-
when VARIANT_SOLID
|
76
|
+
when VARIANT_SOLID, VARIANT_MINI
|
68
77
|
{
|
69
78
|
fill: "currentColor",
|
70
79
|
}
|
@@ -75,7 +84,7 @@ module HeroiconsHelper
|
|
75
84
|
"0 0 #{@width} #{@height}"
|
76
85
|
end
|
77
86
|
|
78
|
-
# determine the height and width of the
|
87
|
+
# determine the height and width of the heroicon based on :size option
|
79
88
|
private def size
|
80
89
|
size = {
|
81
90
|
width: @width,
|
@@ -104,7 +113,7 @@ module HeroiconsHelper
|
|
104
113
|
private def get_heroicon(name, variant)
|
105
114
|
raise ArgumentError, "Icon name can't be empty" if name.empty?
|
106
115
|
|
107
|
-
raise ArgumentError, "Variant `#{variant.inspect}` is invalid; must be one of #{
|
116
|
+
raise ArgumentError, "Variant `#{variant.inspect}` is invalid; must be one of #{VALID_VARIANTS.join(", ")}" unless VALID_VARIANTS.include?(variant)
|
108
117
|
|
109
118
|
icon = HeroiconsHelper::ICON_NAMES[name]
|
110
119
|
|
data/lib/heroicons_helper.rb
CHANGED
@@ -9,18 +9,19 @@ module HeroiconsHelper
|
|
9
9
|
file_data = File.read(File.join(File.dirname(__FILE__), "./heroicons_helper/data.json"))
|
10
10
|
ICON_NAMES = JSON.parse(file_data).freeze
|
11
11
|
|
12
|
-
def heroicon(name, variant:, **attributes)
|
12
|
+
def heroicon(name, variant:, unsafe: false, **attributes)
|
13
13
|
cache_key = HeroiconsHelper::Cache.get_key(
|
14
14
|
name: name,
|
15
15
|
variant: variant,
|
16
|
+
unsafe: unsafe,
|
16
17
|
height: attributes[:height],
|
17
|
-
width: attributes[:width]
|
18
|
+
width: attributes[:width],
|
18
19
|
)
|
19
20
|
|
20
21
|
cached_heroicon = HeroiconsHelper::Cache.read(cache_key)
|
21
22
|
return cached_heroicon unless cached_heroicon.nil?
|
22
23
|
|
23
|
-
heroicon = ::HeroiconsHelper::Icon.new(name, variant, attributes: attributes)
|
24
|
+
heroicon = ::HeroiconsHelper::Icon.new(name, variant, unsafe: unsafe, attributes: attributes)
|
24
25
|
HeroiconsHelper::Cache.set(cache_key, heroicon)
|
25
26
|
|
26
27
|
heroicon
|
data/package-lock.json
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
"cheerio": "1.0.0-rc.11",
|
10
10
|
"fs-extra": "^7.0.1",
|
11
11
|
"globby": "11.0.0",
|
12
|
-
"heroicons": "^
|
12
|
+
"heroicons": "^2.0.0",
|
13
13
|
"lodash.merge": "4.6.2",
|
14
14
|
"trim-newlines": "3.0.1",
|
15
15
|
"yargs": "15.1.0"
|
@@ -289,9 +289,9 @@
|
|
289
289
|
"dev": true
|
290
290
|
},
|
291
291
|
"node_modules/entities": {
|
292
|
-
"version": "4.3.
|
293
|
-
"resolved": "https://registry.npmjs.org/entities/-/entities-4.3.
|
294
|
-
"integrity": "sha512
|
292
|
+
"version": "4.3.1",
|
293
|
+
"resolved": "https://registry.npmjs.org/entities/-/entities-4.3.1.tgz",
|
294
|
+
"integrity": "sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg==",
|
295
295
|
"dev": true,
|
296
296
|
"engines": {
|
297
297
|
"node": ">=0.12"
|
@@ -412,9 +412,9 @@
|
|
412
412
|
"dev": true
|
413
413
|
},
|
414
414
|
"node_modules/heroicons": {
|
415
|
-
"version": "
|
416
|
-
"resolved": "https://registry.npmjs.org/heroicons/-/heroicons-
|
417
|
-
"integrity": "sha512-
|
415
|
+
"version": "2.0.7",
|
416
|
+
"resolved": "https://registry.npmjs.org/heroicons/-/heroicons-2.0.7.tgz",
|
417
|
+
"integrity": "sha512-BuYwHlgmMIPy1lut5ADTZnsk/FqenSx9f9UxbbABDtTO2GV0Ec/k7VgDs6CCcEnaZ8IDH9mbzyeS/HVpqpxXnQ==",
|
418
418
|
"dev": true
|
419
419
|
},
|
420
420
|
"node_modules/htmlparser2": {
|
@@ -784,7 +784,7 @@
|
|
784
784
|
"node_modules/which-module": {
|
785
785
|
"version": "2.0.0",
|
786
786
|
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
|
787
|
-
"integrity": "
|
787
|
+
"integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==",
|
788
788
|
"dev": true
|
789
789
|
},
|
790
790
|
"node_modules/wrap-ansi": {
|
@@ -1043,9 +1043,9 @@
|
|
1043
1043
|
"dev": true
|
1044
1044
|
},
|
1045
1045
|
"entities": {
|
1046
|
-
"version": "4.3.
|
1047
|
-
"resolved": "https://registry.npmjs.org/entities/-/entities-4.3.
|
1048
|
-
"integrity": "sha512
|
1046
|
+
"version": "4.3.1",
|
1047
|
+
"resolved": "https://registry.npmjs.org/entities/-/entities-4.3.1.tgz",
|
1048
|
+
"integrity": "sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg==",
|
1049
1049
|
"dev": true
|
1050
1050
|
},
|
1051
1051
|
"fast-glob": {
|
@@ -1136,9 +1136,9 @@
|
|
1136
1136
|
"dev": true
|
1137
1137
|
},
|
1138
1138
|
"heroicons": {
|
1139
|
-
"version": "
|
1140
|
-
"resolved": "https://registry.npmjs.org/heroicons/-/heroicons-
|
1141
|
-
"integrity": "sha512-
|
1139
|
+
"version": "2.0.7",
|
1140
|
+
"resolved": "https://registry.npmjs.org/heroicons/-/heroicons-2.0.7.tgz",
|
1141
|
+
"integrity": "sha512-BuYwHlgmMIPy1lut5ADTZnsk/FqenSx9f9UxbbABDtTO2GV0Ec/k7VgDs6CCcEnaZ8IDH9mbzyeS/HVpqpxXnQ==",
|
1142
1142
|
"dev": true
|
1143
1143
|
},
|
1144
1144
|
"htmlparser2": {
|
@@ -1391,7 +1391,7 @@
|
|
1391
1391
|
"which-module": {
|
1392
1392
|
"version": "2.0.0",
|
1393
1393
|
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
|
1394
|
-
"integrity": "
|
1394
|
+
"integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==",
|
1395
1395
|
"dev": true
|
1396
1396
|
},
|
1397
1397
|
"wrap-ansi": {
|
data/package.json
CHANGED
data/script/keywords.json
CHANGED
data/script/update_heroicons
CHANGED
@@ -19,8 +19,9 @@ const { argv } = yargs
|
|
19
19
|
type: "array",
|
20
20
|
describe: "Input SVG files",
|
21
21
|
default: [
|
22
|
-
"node_modules/heroicons/outline/*.svg",
|
23
|
-
"node_modules/heroicons/solid/*.svg",
|
22
|
+
"node_modules/heroicons/24/outline/*.svg",
|
23
|
+
"node_modules/heroicons/24/solid/*.svg",
|
24
|
+
"node_modules/heroicons/20/solid/*.svg",
|
24
25
|
],
|
25
26
|
})
|
26
27
|
.option("output", {
|
@@ -38,45 +39,28 @@ const svgFilepaths = filepaths.filter(
|
|
38
39
|
|
39
40
|
if (svgFilepaths.length === 0) {
|
40
41
|
// eslint-disable-next-line no-console
|
41
|
-
console.error(`No input SVG file(s) found in ${
|
42
|
+
console.error(`No input SVG file(s) found in ${filepaths.join(", ")}`);
|
42
43
|
process.exit(1);
|
43
44
|
}
|
44
45
|
|
45
46
|
let exitCode = 0;
|
46
47
|
|
47
|
-
const validTypes = ["solid", "outline"];
|
48
|
-
const defaultOutlineWidth = "24";
|
49
|
-
const defaultSolidWidth = "
|
48
|
+
const validTypes = ["solid", "outline", "mini"];
|
49
|
+
const defaultOutlineWidth = parseInt("24");
|
50
|
+
const defaultSolidWidth = parseInt("24");
|
51
|
+
const defaultMiniWidth = parseInt("20");
|
50
52
|
|
51
53
|
const icons = svgFilepaths.map((filepath) => {
|
52
54
|
try {
|
53
|
-
|
54
|
-
|
55
|
-
let
|
56
|
-
|
57
|
-
case "outline":
|
58
|
-
widthSize = defaultOutlineWidth;
|
59
|
-
break;
|
60
|
-
case "solid":
|
61
|
-
widthSize = defaultSolidWidth;
|
62
|
-
break;
|
63
|
-
default:
|
64
|
-
throw new Error(`Unknown icon type: ${type}`);
|
65
|
-
}
|
66
|
-
|
67
|
-
const filenamePattern = /(.+)(?:-[0-9]{1,2})?-([0-9]{2}).svg$/;
|
68
|
-
const filenameReplacePattern = /\.svg$/;
|
69
|
-
|
70
|
-
if (!filenamePattern.test(filename)) {
|
71
|
-
filename = filename.replace(filenameReplacePattern, `-${widthSize}.svg`);
|
72
|
-
}
|
73
|
-
|
74
|
-
const [, name, height] = filename.match(filenamePattern);
|
55
|
+
const filename = path.parse(filepath).base;
|
56
|
+
let splitDir = path.parse(filepath).dir.split("/");
|
57
|
+
let type = splitDir.pop();
|
58
|
+
const size = splitDir.pop();
|
75
59
|
|
76
60
|
const svg = fs.readFileSync(path.resolve(filepath), "utf8");
|
77
61
|
const svgElement = cheerio.load(svg)("svg");
|
78
|
-
let svgWidth = parseInt(svgElement.attr("width"));
|
79
|
-
let svgHeight = parseInt(svgElement.attr("height"));
|
62
|
+
let svgWidth = parseInt(svgElement.attr("width")) || parseInt(size);
|
63
|
+
let svgHeight = parseInt(svgElement.attr("height")) || parseInt(size);
|
80
64
|
const svgViewBox = svgElement.attr("viewBox");
|
81
65
|
const svgPath = trimNewlines(svgElement.html()).trim();
|
82
66
|
|
@@ -94,12 +78,6 @@ const icons = svgFilepaths.map((filepath) => {
|
|
94
78
|
throw new Error(`${filename}: Missing viewBox attribute.`);
|
95
79
|
}
|
96
80
|
|
97
|
-
if (svgHeight != parseInt(height)) {
|
98
|
-
throw new Error(
|
99
|
-
`${filename}: Height in filename (${height}) does not match height attribute of SVG (${svgHeight})`
|
100
|
-
);
|
101
|
-
}
|
102
|
-
|
103
81
|
const viewBoxPattern = /0 0 ([0-9]+) ([0-9]+)/;
|
104
82
|
|
105
83
|
if (!viewBoxPattern.test(svgViewBox)) {
|
@@ -122,6 +100,11 @@ const icons = svgFilepaths.map((filepath) => {
|
|
122
100
|
);
|
123
101
|
}
|
124
102
|
|
103
|
+
if (svgWidth == defaultMiniWidth && type == "solid") {
|
104
|
+
type = "mini";
|
105
|
+
}
|
106
|
+
const name = filename.slice(0, -4);
|
107
|
+
|
125
108
|
return {
|
126
109
|
name,
|
127
110
|
keywords: keywords[name] || [],
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: heroicons_helper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Garen J. Torikian
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
12
|
-
dependencies:
|
11
|
+
date: 2022-09-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '6'
|
13
27
|
description: A package that distributes Heroicons as a gem, for easy inclusion in
|
14
28
|
Ruby projects.
|
15
29
|
email:
|
@@ -38,8 +52,8 @@ homepage: https://github.com/gjtorikian/heroicons_helper
|
|
38
52
|
licenses:
|
39
53
|
- MIT
|
40
54
|
metadata:
|
41
|
-
|
42
|
-
|
55
|
+
funding_uri: https://github.com/sponsors/gjtorikian/
|
56
|
+
rubygems_mfa_required: 'true'
|
43
57
|
post_install_message:
|
44
58
|
rdoc_options: []
|
45
59
|
require_paths:
|