heroicons_helper 0.4.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,19 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "set"
4
+
3
5
  module HeroiconsHelper
4
6
  # Icon to show heroicons by name and variant.
5
7
  class Icon
6
- attr_reader :path, :attributes, :width, :height, :symbol, :variant, :keywords
8
+ attr_reader :path, :attributes, :width, :height, :name, :variant, :keywords
7
9
 
8
10
  VARIANT_OUTLINE = "outline"
9
11
  VARIANT_SOLID = "solid"
10
- VARIANTS = [VARIANT_OUTLINE, VARIANT_SOLID].freeze
12
+ VARIANT_MINI = "mini"
13
+ VALID_VARIANTS = Set.new([VARIANT_OUTLINE, VARIANT_SOLID, VARIANT_MINI]).freeze
11
14
 
12
- def initialize(symbol, variant, attributes: {})
13
- @symbol = symbol.to_s
15
+ def initialize(name, variant, attributes: {})
16
+ @name = name.to_s
14
17
  @variant = variant.to_s
15
18
 
16
- heroicon = get_heroicon(@symbol, @variant)
19
+ heroicon = get_heroicon(@name, @variant)
17
20
 
18
21
  @path = heroicon["path"]
19
22
  @width = heroicon["width"]
@@ -30,7 +33,7 @@ module HeroiconsHelper
30
33
 
31
34
  # Returns an string representing a <svg> tag
32
35
  def to_svg
33
- "<svg xmlns=\"http://www.w3.org/2000/svg\" #{html_attributes}>#{@path}</svg>"
36
+ "<!-- Heroicon name: #{@variant}/#{@name} --><svg xmlns=\"http://www.w3.org/2000/svg\" #{html_attributes}>#{@path}</svg>"
34
37
  end
35
38
 
36
39
  private def html_attributes
@@ -52,9 +55,9 @@ module HeroiconsHelper
52
55
  accessible
53
56
  end
54
57
 
55
- # prepare the octicon class
58
+ # prepare the heroicon class
56
59
  private def classes
57
- "heroicon heroicon-#{@symbol}-#{@variant} #{@attributes[:class]} ".strip
60
+ "heroicon heroicon-#{@name}-#{@variant} #{@attributes[:class]} ".strip
58
61
  end
59
62
 
60
63
  private def variant_attributes
@@ -64,7 +67,7 @@ module HeroiconsHelper
64
67
  fill: "none",
65
68
  stroke: "currentColor",
66
69
  }
67
- when VARIANT_SOLID
70
+ when VARIANT_SOLID, VARIANT_MINI
68
71
  {
69
72
  fill: "currentColor",
70
73
  }
@@ -75,7 +78,7 @@ module HeroiconsHelper
75
78
  "0 0 #{@width} #{@height}"
76
79
  end
77
80
 
78
- # determine the height and width of the octicon based on :size option
81
+ # determine the height and width of the heroicon based on :size option
79
82
  private def size
80
83
  size = {
81
84
  width: @width,
@@ -101,17 +104,17 @@ module HeroiconsHelper
101
104
  (width.to_i * @height) / @width
102
105
  end
103
106
 
104
- private def get_heroicon(symbol, variant)
105
- raise ArgumentError, "Icon name can't be empty" if symbol.empty?
107
+ private def get_heroicon(name, variant)
108
+ raise ArgumentError, "Icon name can't be empty" if name.empty?
106
109
 
107
- raise ArgumentError, "Variant `#{variant.inspect}` is invalid; must be one of #{VARIANTS.join(", ")}" unless VARIANTS.include?(variant)
110
+ raise ArgumentError, "Variant `#{variant.inspect}` is invalid; must be one of #{VALID_VARIANTS.join(", ")}" unless VALID_VARIANTS.include?(variant)
108
111
 
109
- icon = HeroiconsHelper::ICON_SYMBOLS[symbol]
112
+ icon = HeroiconsHelper::ICON_NAMES[name]
110
113
 
111
- raise ArgumentError, "Couldn't find Heroicon for `#{symbol.inspect}`" unless icon
114
+ raise ArgumentError, "Couldn't find Heroicon for `#{name.inspect}`" unless icon
112
115
 
113
116
  icon_variant = icon["variants"][variant]
114
- raise ArgumentError, "Heroicon for `#{symbol.inspect}` doesn't have variant `#{variant.inspect}`" unless icon_variant
117
+ raise ArgumentError, "Heroicon for `#{name.inspect}` doesn't have variant `#{variant.inspect}`" unless icon_variant
115
118
 
116
119
  {
117
120
  "name" => icon["name"],
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HeroiconsHelper
4
- VERSION = "0.4.1"
4
+ VERSION = "0.6.0"
5
5
  end
@@ -7,9 +7,22 @@ require "json"
7
7
 
8
8
  module HeroiconsHelper
9
9
  file_data = File.read(File.join(File.dirname(__FILE__), "./heroicons_helper/data.json"))
10
- ICON_SYMBOLS = JSON.parse(file_data).freeze
10
+ ICON_NAMES = JSON.parse(file_data).freeze
11
11
 
12
- def heroicon(symbol, variant:, **attributes)
13
- ::HeroiconsHelper::Icon.new(symbol, variant, attributes: attributes)
12
+ def heroicon(name, variant:, **attributes)
13
+ cache_key = HeroiconsHelper::Cache.get_key(
14
+ name: name,
15
+ variant: variant,
16
+ height: attributes[:height],
17
+ width: attributes[:width]
18
+ )
19
+
20
+ cached_heroicon = HeroiconsHelper::Cache.read(cache_key)
21
+ return cached_heroicon unless cached_heroicon.nil?
22
+
23
+ heroicon = ::HeroiconsHelper::Icon.new(name, variant, attributes: attributes)
24
+ HeroiconsHelper::Cache.set(cache_key, heroicon)
25
+
26
+ heroicon
14
27
  end
15
28
  end
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": "^1.0.6",
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.0",
293
- "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.0.tgz",
294
- "integrity": "sha512-/iP1rZrSEJ0DTlPiX+jbzlA3eVkY/e8L8SozroF395fIqE3TYF/Nz7YOMAawta+vLmyJ/hkGNNPcSbMADCCXbg==",
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": "1.0.6",
416
- "resolved": "https://registry.npmjs.org/heroicons/-/heroicons-1.0.6.tgz",
417
- "integrity": "sha512-5bxTsG2hyNBF0l+BrFlZlR5YngQNMfl0ggJjIRkMSADBQbaZMoTg47OIQzq6f1mpEZ85HEIgSC4wt5AeFM9J2Q==",
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": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
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.0",
1047
- "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.0.tgz",
1048
- "integrity": "sha512-/iP1rZrSEJ0DTlPiX+jbzlA3eVkY/e8L8SozroF395fIqE3TYF/Nz7YOMAawta+vLmyJ/hkGNNPcSbMADCCXbg==",
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": "1.0.6",
1140
- "resolved": "https://registry.npmjs.org/heroicons/-/heroicons-1.0.6.tgz",
1141
- "integrity": "sha512-5bxTsG2hyNBF0l+BrFlZlR5YngQNMfl0ggJjIRkMSADBQbaZMoTg47OIQzq6f1mpEZ85HEIgSC4wt5AeFM9J2Q==",
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": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
1394
+ "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==",
1395
1395
  "dev": true
1396
1396
  },
1397
1397
  "wrap-ansi": {
data/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "private": true,
4
4
  "devDependencies": {
5
5
  "cheerio": "1.0.0-rc.11",
6
- "heroicons": "^1.0.6",
6
+ "heroicons": "^2.0.0",
7
7
  "fs-extra": "^7.0.1",
8
8
  "globby": "11.0.0",
9
9
  "lodash.merge": "4.6.2",
data/script/keywords.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "archive": ["box", "catalog"]
2
+ "archive-box": ["box", "catalog"]
3
3
  }
@@ -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 ${icon_file_path.join(", ")}`);
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 = "20";
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
- let filename = path.parse(filepath).base;
54
- const type = path.parse(filepath).dir.split("/").pop();
55
- let widthSize;
56
- switch (type) {
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,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.1
4
+ version: 0.6.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-06-11 00:00:00.000000000 Z
11
+ date: 2022-08-26 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A package that distributes Heroicons as a gem, for easy inclusion in
14
14
  Ruby projects.