heroicons_helper 0.7.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.vscode/settings.json +6 -0
- data/CHANGELOG.md +2 -0
- data/lib/heroicons_helper/cache.rb +2 -9
- data/lib/heroicons_helper/data.json +1 -1
- data/lib/heroicons_helper/icon.rb +22 -51
- data/lib/heroicons_helper/version.rb +1 -1
- data/lib/heroicons_helper.rb +4 -4
- data/package-lock.json +15 -15
- data/script/update_heroicons +22 -10
- metadata +3 -3
@@ -6,36 +6,37 @@ require "active_support/core_ext/string/output_safety"
|
|
6
6
|
module HeroiconsHelper
|
7
7
|
# Icon to show heroicons by name and variant.
|
8
8
|
class Icon
|
9
|
-
attr_reader :
|
9
|
+
attr_reader :inner, :attributes, :width, :height, :name, :variant, :keywords
|
10
10
|
|
11
11
|
VARIANT_OUTLINE = "outline"
|
12
12
|
VARIANT_SOLID = "solid"
|
13
13
|
VARIANT_MINI = "mini"
|
14
|
-
|
14
|
+
VARIANT_MICRO = "micro"
|
15
|
+
VALID_VARIANTS = Set.new([VARIANT_OUTLINE, VARIANT_SOLID, VARIANT_MINI, VARIANT_MICRO]).freeze
|
15
16
|
|
16
|
-
def initialize(name, variant,
|
17
|
+
def initialize(name, variant, size: nil, attributes: {})
|
17
18
|
@name = name.to_s
|
18
19
|
@variant = variant.to_s
|
19
|
-
@unsafe = unsafe
|
20
20
|
|
21
21
|
heroicon = get_heroicon(@name, @variant)
|
22
22
|
|
23
|
-
@
|
24
|
-
@width = heroicon["width"]
|
25
|
-
@height = heroicon["height"]
|
23
|
+
@inner = heroicon["inner"]
|
24
|
+
@width = size || heroicon["width"]
|
25
|
+
@height = size || heroicon["height"]
|
26
26
|
@keywords = heroicon["keywords"]
|
27
|
-
@attributes = attributes.
|
28
|
-
@attributes
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
27
|
+
@attributes = attributes.merge(heroicon["attributes"])
|
28
|
+
@attributes.merge!({
|
29
|
+
"class" => classes,
|
30
|
+
"viewBox" => viewbox,
|
31
|
+
"version" => "1.1",
|
32
|
+
})
|
33
|
+
.merge!(a11y)
|
34
|
+
.compact!
|
34
35
|
end
|
35
36
|
|
36
37
|
# Returns an string representing a <svg> tag
|
37
38
|
def to_svg
|
38
|
-
"
|
39
|
+
"<svg #{html_attributes}>#{@inner}</svg>"
|
39
40
|
end
|
40
41
|
|
41
42
|
private def safe?
|
@@ -53,9 +54,9 @@ module HeroiconsHelper
|
|
53
54
|
accessible = {}
|
54
55
|
|
55
56
|
if @attributes[:"aria-label"].nil? && @attributes["aria-label"].nil?
|
56
|
-
accessible[
|
57
|
+
accessible["aria-hidden"] = "true"
|
57
58
|
else
|
58
|
-
accessible[
|
59
|
+
accessible["role"] = "img"
|
59
60
|
end
|
60
61
|
|
61
62
|
accessible
|
@@ -63,44 +64,13 @@ module HeroiconsHelper
|
|
63
64
|
|
64
65
|
# prepare the heroicon class
|
65
66
|
private def classes
|
66
|
-
"heroicon heroicon-#{@
|
67
|
-
end
|
68
|
-
|
69
|
-
private def variant_attributes
|
70
|
-
case @variant
|
71
|
-
when VARIANT_OUTLINE
|
72
|
-
{
|
73
|
-
fill: "none",
|
74
|
-
}
|
75
|
-
when VARIANT_SOLID, VARIANT_MINI
|
76
|
-
{
|
77
|
-
fill: "currentColor",
|
78
|
-
}
|
79
|
-
end
|
67
|
+
"heroicon heroicon-#{@variant}-#{@name} #{@attributes[:class]} ".strip
|
80
68
|
end
|
81
69
|
|
82
70
|
private def viewbox
|
83
71
|
"0 0 #{@width} #{@height}"
|
84
72
|
end
|
85
73
|
|
86
|
-
# determine the height and width of the heroicon based on :size option
|
87
|
-
private def size
|
88
|
-
size = {
|
89
|
-
width: @width,
|
90
|
-
height: @height,
|
91
|
-
}
|
92
|
-
|
93
|
-
# Specific size
|
94
|
-
unless @attributes[:width].nil? && @attributes[:height].nil?
|
95
|
-
size[:width] = @attributes[:width].nil? ? calculate_width(@attributes[:height]) : @attributes[:width]
|
96
|
-
size[:height] = @attributes[:height].nil? ? calculate_height(@attributes[:width]) : @attributes[:height]
|
97
|
-
@width = size[:width]
|
98
|
-
@height = size[:height]
|
99
|
-
end
|
100
|
-
|
101
|
-
size
|
102
|
-
end
|
103
|
-
|
104
74
|
private def calculate_width(height)
|
105
75
|
(height.to_i * @width) / @height
|
106
76
|
end
|
@@ -114,7 +84,7 @@ module HeroiconsHelper
|
|
114
84
|
|
115
85
|
raise ArgumentError, "Variant `#{variant.inspect}` is invalid; must be one of #{VALID_VARIANTS.join(", ")}" unless VALID_VARIANTS.include?(variant)
|
116
86
|
|
117
|
-
icon = HeroiconsHelper::
|
87
|
+
icon = HeroiconsHelper::ICONS[name]
|
118
88
|
|
119
89
|
raise ArgumentError, "Couldn't find Heroicon for `#{name.inspect}`" unless icon
|
120
90
|
|
@@ -127,7 +97,8 @@ module HeroiconsHelper
|
|
127
97
|
"keywords" => icon["keywords"] || [],
|
128
98
|
"width" => icon_variant["width"],
|
129
99
|
"height" => icon_variant["height"],
|
130
|
-
"
|
100
|
+
"attributes" => icon_variant["attributes"],
|
101
|
+
"inner" => icon_variant["inner"],
|
131
102
|
}
|
132
103
|
end
|
133
104
|
end
|
data/lib/heroicons_helper.rb
CHANGED
@@ -7,20 +7,20 @@ require "json"
|
|
7
7
|
|
8
8
|
module HeroiconsHelper
|
9
9
|
file_data = File.read(File.join(File.dirname(__FILE__), "./heroicons_helper/data.json"))
|
10
|
-
|
10
|
+
ICONS = JSON.parse(file_data).freeze
|
11
11
|
|
12
|
-
def heroicon(name, variant:,
|
12
|
+
def heroicon(name, variant:, size: nil, **attributes)
|
13
13
|
cache_key = HeroiconsHelper::Cache.get_key(
|
14
14
|
name: name,
|
15
15
|
variant: variant,
|
16
|
-
|
16
|
+
size: size,
|
17
17
|
attributes: attributes,
|
18
18
|
)
|
19
19
|
|
20
20
|
cached_heroicon = HeroiconsHelper::Cache.read(cache_key)
|
21
21
|
return cached_heroicon unless cached_heroicon.nil?
|
22
22
|
|
23
|
-
heroicon = ::HeroiconsHelper::Icon.new(name, variant,
|
23
|
+
heroicon = ::HeroiconsHelper::Icon.new(name, variant, size: size, attributes: attributes)
|
24
24
|
HeroiconsHelper::Cache.set(cache_key, heroicon)
|
25
25
|
|
26
26
|
heroicon
|
data/package-lock.json
CHANGED
@@ -301,9 +301,9 @@
|
|
301
301
|
}
|
302
302
|
},
|
303
303
|
"node_modules/fast-glob": {
|
304
|
-
"version": "3.3.
|
305
|
-
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.
|
306
|
-
"integrity": "sha512-
|
304
|
+
"version": "3.3.2",
|
305
|
+
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
|
306
|
+
"integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
|
307
307
|
"dev": true,
|
308
308
|
"dependencies": {
|
309
309
|
"@nodelib/fs.stat": "^2.0.2",
|
@@ -317,9 +317,9 @@
|
|
317
317
|
}
|
318
318
|
},
|
319
319
|
"node_modules/fastq": {
|
320
|
-
"version": "1.
|
321
|
-
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.
|
322
|
-
"integrity": "sha512-
|
320
|
+
"version": "1.17.1",
|
321
|
+
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
|
322
|
+
"integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
|
323
323
|
"dev": true,
|
324
324
|
"dependencies": {
|
325
325
|
"reusify": "^1.0.4"
|
@@ -412,9 +412,9 @@
|
|
412
412
|
"dev": true
|
413
413
|
},
|
414
414
|
"node_modules/heroicons": {
|
415
|
-
"version": "2.
|
416
|
-
"resolved": "https://registry.npmjs.org/heroicons/-/heroicons-2.
|
417
|
-
"integrity": "sha512-
|
415
|
+
"version": "2.1.3",
|
416
|
+
"resolved": "https://registry.npmjs.org/heroicons/-/heroicons-2.1.3.tgz",
|
417
|
+
"integrity": "sha512-Fom8AaUho83oeGPCne9oo1F6A+2r4BPmY59qOkML4LIu+xQNS/yv8OmcrxCuiVs7X42oTRAnFbOJHGDwIlI8HA==",
|
418
418
|
"dev": true
|
419
419
|
},
|
420
420
|
"node_modules/htmlparser2": {
|
@@ -437,9 +437,9 @@
|
|
437
437
|
}
|
438
438
|
},
|
439
439
|
"node_modules/ignore": {
|
440
|
-
"version": "5.
|
441
|
-
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.
|
442
|
-
"integrity": "sha512-
|
440
|
+
"version": "5.3.1",
|
441
|
+
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
|
442
|
+
"integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
|
443
443
|
"dev": true,
|
444
444
|
"engines": {
|
445
445
|
"node": ">= 4"
|
@@ -767,9 +767,9 @@
|
|
767
767
|
}
|
768
768
|
},
|
769
769
|
"node_modules/tslib": {
|
770
|
-
"version": "2.6.
|
771
|
-
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.
|
772
|
-
"integrity": "sha512-
|
770
|
+
"version": "2.6.2",
|
771
|
+
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
772
|
+
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
|
773
773
|
"dev": true
|
774
774
|
},
|
775
775
|
"node_modules/universalify": {
|
data/script/update_heroicons
CHANGED
@@ -19,9 +19,10 @@ const { argv } = yargs
|
|
19
19
|
type: "array",
|
20
20
|
describe: "Input SVG files",
|
21
21
|
default: [
|
22
|
+
"node_modules/heroicons/16/solid/*.svg",
|
23
|
+
"node_modules/heroicons/20/solid/*.svg",
|
22
24
|
"node_modules/heroicons/24/outline/*.svg",
|
23
25
|
"node_modules/heroicons/24/solid/*.svg",
|
24
|
-
"node_modules/heroicons/20/solid/*.svg",
|
25
26
|
],
|
26
27
|
})
|
27
28
|
.option("output", {
|
@@ -45,24 +46,31 @@ if (svgFilepaths.length === 0) {
|
|
45
46
|
|
46
47
|
let exitCode = 0;
|
47
48
|
|
48
|
-
const validTypes = ["
|
49
|
+
const validTypes = ["micro", "mini", "outline", "solid"];
|
49
50
|
const defaultOutlineWidth = parseInt("24");
|
50
51
|
const defaultSolidWidth = parseInt("24");
|
51
52
|
const defaultMiniWidth = parseInt("20");
|
53
|
+
const defaultMicroWidth = parseInt("16");
|
54
|
+
|
55
|
+
function omit(obj, key) {
|
56
|
+
const { [key]: ignore, ...rest } = obj;
|
57
|
+
return rest;
|
58
|
+
}
|
52
59
|
|
53
60
|
const icons = svgFilepaths.map((filepath) => {
|
54
61
|
try {
|
55
62
|
const filename = path.parse(filepath).base;
|
56
63
|
let splitDir = path.parse(filepath).dir.split("/");
|
57
|
-
let
|
64
|
+
let variant = splitDir.pop();
|
58
65
|
const size = splitDir.pop();
|
59
66
|
|
60
67
|
const svg = fs.readFileSync(path.resolve(filepath), "utf8");
|
61
68
|
const svgElement = cheerio.load(svg)("svg");
|
69
|
+
let svgAttributes = omit(svgElement[0].attribs, "aria-hidden");
|
62
70
|
let svgWidth = parseInt(svgElement.attr("width")) || parseInt(size);
|
63
71
|
let svgHeight = parseInt(svgElement.attr("height")) || parseInt(size);
|
64
72
|
const svgViewBox = svgElement.attr("viewBox");
|
65
|
-
const
|
73
|
+
const svgInner = trimNewlines(svgElement.html()).trim();
|
66
74
|
|
67
75
|
if (!svgWidth) {
|
68
76
|
svgWidth = parseInt(widthSize);
|
@@ -100,18 +108,21 @@ const icons = svgFilepaths.map((filepath) => {
|
|
100
108
|
);
|
101
109
|
}
|
102
110
|
|
103
|
-
if (svgWidth ==
|
104
|
-
|
111
|
+
if (svgWidth == defaultMicroWidth && variant == "solid") {
|
112
|
+
variant = "micro";
|
113
|
+
} else if (svgWidth == defaultMiniWidth && variant == "solid") {
|
114
|
+
variant = "mini";
|
105
115
|
}
|
106
116
|
const name = filename.slice(0, -4);
|
107
117
|
|
108
118
|
return {
|
109
119
|
name,
|
110
120
|
keywords: keywords[name] || [],
|
111
|
-
|
121
|
+
variant: variant,
|
112
122
|
width: svgWidth,
|
113
123
|
height: svgHeight,
|
114
|
-
|
124
|
+
attributes: svgAttributes,
|
125
|
+
inner: svgInner,
|
115
126
|
};
|
116
127
|
} catch (error) {
|
117
128
|
// eslint-disable-next-line no-console
|
@@ -138,10 +149,11 @@ const iconsByName = icons.reduce(
|
|
138
149
|
name: icon.name,
|
139
150
|
keywords: icon.keywords,
|
140
151
|
variants: {
|
141
|
-
[icon.
|
152
|
+
[icon.variant]: {
|
153
|
+
attributes: icon.attributes,
|
142
154
|
width: icon.width,
|
143
155
|
height: icon.height,
|
144
|
-
|
156
|
+
inner: icon.inner,
|
145
157
|
},
|
146
158
|
},
|
147
159
|
},
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: heroicons_helper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.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:
|
11
|
+
date: 2024-04-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -75,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
75
75
|
- !ruby/object:Gem::Version
|
76
76
|
version: '0'
|
77
77
|
requirements: []
|
78
|
-
rubygems_version: 3.4.
|
78
|
+
rubygems_version: 3.4.6
|
79
79
|
signing_key:
|
80
80
|
specification_version: 4
|
81
81
|
summary: Heroicons port for Ruby
|