heroicons_helper 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.
data/package.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "heroicons_helper",
3
+ "private": true,
4
+ "devDependencies": {
5
+ "cheerio": "1.0.0-rc.11",
6
+ "heroicons": "^1.0.6",
7
+ "fs-extra": "^7.0.1",
8
+ "globby": "11.0.0",
9
+ "lodash.merge": "4.6.2",
10
+ "trim-newlines": "3.0.1",
11
+ "yargs": "15.1.0"
12
+ }
13
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "archive": ["box", "catalog"]
3
+ }
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env node
2
+ /* eslint-env node */
3
+ const fs = require("fs-extra");
4
+ const path = require("path");
5
+ const globby = require("globby");
6
+ const cheerio = require("cheerio");
7
+ const trimNewlines = require("trim-newlines");
8
+ const yargs = require("yargs");
9
+ const merge = require("lodash.merge");
10
+ const keywords = require("./keywords.json");
11
+
12
+ // This script generates a JSON file that contains
13
+ // information about input SVG files.
14
+ const { argv } = yargs
15
+ .usage("Usage: $0 --output <output filepath>")
16
+ .example("$0 --input icons/**/*.svg --output build/data.json")
17
+ .option("input", {
18
+ alias: "i",
19
+ type: "array",
20
+ describe: "Input SVG files",
21
+ default: [
22
+ "node_modules/heroicons/outline/*.svg",
23
+ "node_modules/heroicons/solid/*.svg",
24
+ ],
25
+ })
26
+ .option("output", {
27
+ alias: "o",
28
+ type: "string",
29
+ describe:
30
+ "Output JSON file. Defaults to stdout if no output file is provided.",
31
+ default: "lib/heroicons_helper/data.json",
32
+ });
33
+
34
+ const filepaths = globby.sync(argv.input);
35
+ const svgFilepaths = filepaths.filter(
36
+ (filepath) => path.parse(filepath).ext === ".svg"
37
+ );
38
+
39
+ if (svgFilepaths.length === 0) {
40
+ // eslint-disable-next-line no-console
41
+ console.error(`No input SVG file(s) found in ${icon_file_path.join(", ")}`);
42
+ process.exit(1);
43
+ }
44
+
45
+ let exitCode = 0;
46
+
47
+ const validTypes = ["solid", "outline"];
48
+ const defaultOutlineWidth = "24";
49
+ const defaultSolidWidth = "20";
50
+
51
+ const icons = svgFilepaths.map((filepath) => {
52
+ 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);
75
+
76
+ const svg = fs.readFileSync(path.resolve(filepath), "utf8");
77
+ const svgElement = cheerio.load(svg)("svg");
78
+ let svgWidth = parseInt(svgElement.attr("width"));
79
+ let svgHeight = parseInt(svgElement.attr("height"));
80
+ const svgViewBox = svgElement.attr("viewBox");
81
+ const svgPath = trimNewlines(svgElement.html()).trim();
82
+
83
+ if (!svgWidth) {
84
+ svgWidth = parseInt(widthSize);
85
+ svgElement.attr("width", svgWidth);
86
+ }
87
+
88
+ if (!svgHeight) {
89
+ svgHeight = parseInt(widthSize);
90
+ svgElement.attr("height", svgHeight);
91
+ }
92
+
93
+ if (!svgViewBox) {
94
+ throw new Error(`${filename}: Missing viewBox attribute.`);
95
+ }
96
+
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
+ const viewBoxPattern = /0 0 ([0-9]+) ([0-9]+)/;
104
+
105
+ if (!viewBoxPattern.test(svgViewBox)) {
106
+ throw new Error(
107
+ `${filename}: Invalid viewBox attribute. The viewBox attribute should be in the following format: "0 0 <width> <height>"`
108
+ );
109
+ }
110
+
111
+ const [, viewBoxWidth, viewBoxHeight] = svgViewBox.match(viewBoxPattern);
112
+
113
+ if (svgWidth !== parseInt(viewBoxWidth)) {
114
+ throw new Error(
115
+ `${filename}: width attribute and viewBox width do not match.`
116
+ );
117
+ }
118
+
119
+ if (svgHeight !== parseInt(viewBoxHeight)) {
120
+ throw new Error(
121
+ `${filename}: height attribute and viewBox height do not match.`
122
+ );
123
+ }
124
+
125
+ return {
126
+ name,
127
+ keywords: keywords[name] || [],
128
+ type: type,
129
+ width: svgWidth,
130
+ height: svgHeight,
131
+ path: svgPath,
132
+ };
133
+ } catch (error) {
134
+ // eslint-disable-next-line no-console
135
+ console.error(error);
136
+ // Instead of exiting immediately, we set exitCode to 1 and continue
137
+ // iterating through the rest of the SVGs. This allows us to identify all
138
+ // the SVGs that have errors, not just the first one. An exit code of 1
139
+ // indicates that an error occurred.
140
+ // Reference: https://nodejs.org/api/process.html#process_exit_codes
141
+ exitCode = 1;
142
+ return null;
143
+ }
144
+ });
145
+
146
+ // Exit early if any errors occurred.
147
+ if (exitCode !== 0) {
148
+ process.exit(exitCode);
149
+ }
150
+
151
+ const iconsByName = icons.reduce(
152
+ (acc, icon) =>
153
+ merge(acc, {
154
+ [icon.name]: {
155
+ name: icon.name,
156
+ keywords: icon.keywords,
157
+ variants: {
158
+ [icon.type]: {
159
+ width: icon.width,
160
+ height: icon.height,
161
+ path: icon.path,
162
+ },
163
+ },
164
+ },
165
+ }),
166
+ {}
167
+ );
168
+
169
+ fs.outputJsonSync(path.resolve(argv.output), iconsByName);
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: heroicons_helper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Garen J. Torikian
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-06-09 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A package that distributes Heroicons as a gem, for easy inclusion in
14
+ Ruby projects.
15
+ email:
16
+ - gjtorikian@users.noreply.github.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - ".rubocop.yml"
22
+ - CHANGELOG.md
23
+ - Gemfile
24
+ - LICENSE.txt
25
+ - README.md
26
+ - Rakefile
27
+ - heroicons_helper.gemspec
28
+ - lib/heroicons_helper.rb
29
+ - lib/heroicons_helper/data.json
30
+ - lib/heroicons_helper/icon.rb
31
+ - lib/heroicons_helper/version.rb
32
+ - package-lock.json
33
+ - package.json
34
+ - script/keywords.json
35
+ - script/update_heroicons
36
+ homepage: https://github.com/gjtorikian/heroicons_helper
37
+ licenses:
38
+ - MIT
39
+ metadata:
40
+ homepage_uri: https://github.com/gjtorikian/heroicons_helper
41
+ source_code_uri: https://github.com/gjtorikian/heroicons_helper
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 2.7.0
51
+ - - "<"
52
+ - !ruby/object:Gem::Version
53
+ version: 4.0.0
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ requirements: []
60
+ rubygems_version: 3.3.13
61
+ signing_key:
62
+ specification_version: 4
63
+ summary: Heroicons port for Ruby
64
+ test_files: []