@fusion.dev/helix-icons 0.206.0 → 0.207.1
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.
- package/README.md +37 -3
- package/dist/build.d.ts +10 -2
- package/dist/build.js +27 -18
- package/dist/cli.js +44 -24
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -53,9 +53,9 @@ import { peak } from './icons'
|
|
|
53
53
|
<helix-icon icon={peak} />
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
same command against the package it resolves from, and
|
|
58
|
-
that spells a weight into the file name:
|
|
56
|
+
The command reads any set of SVG files. More of Phosphor than this package
|
|
57
|
+
carries is the same command against the package it resolves from, and
|
|
58
|
+
`--suffix` is for a set that spells a weight into the file name:
|
|
59
59
|
|
|
60
60
|
```sh
|
|
61
61
|
npx helix-icons build \
|
|
@@ -67,6 +67,40 @@ npx helix-icons build \
|
|
|
67
67
|
so nothing can drop any of it: ask for it when you want names in markup, and
|
|
68
68
|
leave it off when you import.
|
|
69
69
|
|
|
70
|
+
An `--out` path ending in `.js` or `.mjs` gets JavaScript, with the type in a
|
|
71
|
+
JSDoc comment. Any other path gets TypeScript.
|
|
72
|
+
|
|
73
|
+
### From a script
|
|
74
|
+
|
|
75
|
+
The command is also a module, `@fusion.dev/helix-icons/build`, for a build
|
|
76
|
+
script of your own:
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
import { build } from '@fusion.dev/helix-icons/build'
|
|
80
|
+
|
|
81
|
+
const written = build({
|
|
82
|
+
out: 'src/icons.ts',
|
|
83
|
+
sources: [{ directory: 'brand-icons' }],
|
|
84
|
+
})
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
`build` writes the module and returns how many icons it holds. Its options are
|
|
88
|
+
the command's flags:
|
|
89
|
+
|
|
90
|
+
- `sources`: where the SVG files are, searched in order, each as
|
|
91
|
+
`{ directory, suffix }`;
|
|
92
|
+
- `names`: the icons to build, and every icon in the sources when left out;
|
|
93
|
+
- `out`: where to write the module;
|
|
94
|
+
- `index`: whether to also write the record `<helix-icon name>` reads;
|
|
95
|
+
- `typeImport`: where the module imports `HelixIcon` from.
|
|
96
|
+
|
|
97
|
+
It throws where the command fails:
|
|
98
|
+
|
|
99
|
+
- a source that is not a directory;
|
|
100
|
+
- a name with no file, or with a file in two sources;
|
|
101
|
+
- sources with no SVG files, when `names` is left out;
|
|
102
|
+
- an `out` path ending in `.cjs`.
|
|
103
|
+
|
|
70
104
|
Phosphor is MIT and its notice travels in `LICENSE` beside ours.
|
|
71
105
|
|
|
72
106
|
[Documentation](https://fusion.dev/helix)
|
package/dist/build.d.ts
CHANGED
|
@@ -40,7 +40,13 @@ export interface BuildOptions {
|
|
|
40
40
|
* pointing at their own folder of drawings usually means.
|
|
41
41
|
*/
|
|
42
42
|
names?: string[];
|
|
43
|
-
/**
|
|
43
|
+
/**
|
|
44
|
+
* Where to write the module, creating its directory where there is none.
|
|
45
|
+
*
|
|
46
|
+
* A `.js` or `.mjs` path gets JavaScript, with the type in a JSDoc comment.
|
|
47
|
+
* Any other gets TypeScript, and a `.cjs` path is refused, the module being
|
|
48
|
+
* an ES module.
|
|
49
|
+
*/
|
|
44
50
|
out: string;
|
|
45
51
|
sources: IconSource[];
|
|
46
52
|
/**
|
|
@@ -59,6 +65,8 @@ export interface BuildOptions {
|
|
|
59
65
|
/**
|
|
60
66
|
* Writes the module, and says how many glyphs are in it.
|
|
61
67
|
*
|
|
62
|
-
* @throws where a
|
|
68
|
+
* @throws where a source is not a directory, where a name resolves to no file
|
|
69
|
+
* or to more than one, where the sources hold no glyph and no names were given,
|
|
70
|
+
* and where `out` is a `.cjs` file.
|
|
63
71
|
*/
|
|
64
72
|
export declare function build(options: BuildOptions): number;
|
package/dist/build.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { join } from 'node:path';
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
3
|
import { optimize } from 'svgo';
|
|
4
4
|
const SVGO = {
|
|
5
5
|
multipass: true,
|
|
@@ -9,9 +9,6 @@ const camel = (slug) => slug.replace(/-([a-z0-9])/g, (_, char) => char.toUpperCa
|
|
|
9
9
|
const namesIn = (sources) => {
|
|
10
10
|
const found = new Set();
|
|
11
11
|
for (const { directory, suffix = '' } of sources) {
|
|
12
|
-
if (!existsSync(directory)) {
|
|
13
|
-
continue;
|
|
14
|
-
}
|
|
15
12
|
for (const file of readdirSync(directory)) {
|
|
16
13
|
if (!file.endsWith('.svg')) {
|
|
17
14
|
continue;
|
|
@@ -51,23 +48,35 @@ const drawn = (slug, sources) => {
|
|
|
51
48
|
};
|
|
52
49
|
export function build(options) {
|
|
53
50
|
const { index = false, out, sources, typeImport = '@fusion.dev/helix-icons' } = options;
|
|
51
|
+
if (out.endsWith('.cjs')) {
|
|
52
|
+
throw new Error(`icons: ${out} is a CommonJS file, and the module is an ES module. Name it .js, .mjs, or .ts.`);
|
|
53
|
+
}
|
|
54
|
+
for (const { directory } of sources) {
|
|
55
|
+
if (!existsSync(directory) || !statSync(directory).isDirectory()) {
|
|
56
|
+
throw new Error(`icons: no directory at ${directory}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
54
59
|
const names = options.names ?? namesIn(sources);
|
|
60
|
+
if (options.names === undefined && names.length === 0) {
|
|
61
|
+
const where = sources
|
|
62
|
+
.map(({ directory, suffix = '' }) => suffix === '' ? directory : `${directory} (named *${suffix}.svg)`)
|
|
63
|
+
.join(', ');
|
|
64
|
+
throw new Error(`icons: no SVG files in ${where}`);
|
|
65
|
+
}
|
|
55
66
|
const entries = names.map((slug) => drawn(slug, sources));
|
|
67
|
+
const script = /\.m?js$/.test(out);
|
|
68
|
+
const icon = script ? `import('${typeImport}').HelixIcon` : 'HelixIcon';
|
|
69
|
+
const declared = (name, type) => script ? `/** @type {${type}} */\nexport const ${name} =` : `export const ${name}: ${type} =`;
|
|
56
70
|
const body = entries
|
|
57
|
-
.map(({ camel: name, content, slug, viewBox }) =>
|
|
71
|
+
.map(({ camel: name, content, slug, viewBox }) => `${declared(name, icon)} {\n content: '${content.replace(/'/g, "\\'")}',\n name: '${slug}',\n viewBox: '${viewBox}',\n}`)
|
|
58
72
|
.join('\n\n');
|
|
59
73
|
const record = entries.map(({ camel: name, slug }) => ` '${slug}': ${name},`).join('\n');
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
${
|
|
64
|
-
${
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
export const icons: Record<string, HelixIcon> = {
|
|
68
|
-
${record}
|
|
69
|
-
}
|
|
70
|
-
`
|
|
71
|
-
: ''}`);
|
|
74
|
+
const lookup = 'Every icon, by name, for lookup from a `name` attribute.';
|
|
75
|
+
const indexed = script
|
|
76
|
+
? `/**\n * ${lookup}\n *\n * @type {Record<string, ${icon}>}\n */\nexport const icons =`
|
|
77
|
+
: `/** ${lookup} */\nexport const icons: Record<string, HelixIcon> =`;
|
|
78
|
+
const head = script ? '' : `import type { HelixIcon } from '${typeImport}'\n`;
|
|
79
|
+
mkdirSync(dirname(out), { recursive: true });
|
|
80
|
+
writeFileSync(out, `// Generated by @fusion.dev/helix-icons. Do not edit.\n${head}\n${body}\n${index ? `\n${indexed} {\n${record}\n}\n` : ''}`);
|
|
72
81
|
return entries.length;
|
|
73
82
|
}
|
package/dist/cli.js
CHANGED
|
@@ -9,61 +9,81 @@ const USAGE = `helix-icons build --source <dir> [--suffix <text>] [--list <file>
|
|
|
9
9
|
before it: --source …/bold --suffix -bold reads caret-down-bold.svg.
|
|
10
10
|
--list <file> Names to build, one per line, # for a comment. Default: every
|
|
11
11
|
glyph the sources hold.
|
|
12
|
-
--out <file> Where to write the module.
|
|
12
|
+
--out <file> Where to write the module: JavaScript for a .js or .mjs file,
|
|
13
|
+
TypeScript otherwise. Default: icons.generated.ts
|
|
13
14
|
--index Also write the record \`<helix-icon name>\` reads. It names every
|
|
14
15
|
glyph, so nothing can drop any of it: for markup, not for imports.
|
|
15
16
|
--type-import <s> Where the module imports \`HelixIcon\` from.
|
|
16
|
-
Default: @fusion.dev/helix-icons
|
|
17
|
+
Default: @fusion.dev/helix-icons
|
|
18
|
+
-h, --help Print this.`;
|
|
17
19
|
const after = (argv, at) => {
|
|
18
20
|
const value = argv[at + 1];
|
|
19
21
|
return value === undefined || value.startsWith('--') ? undefined : value;
|
|
20
22
|
};
|
|
23
|
+
const refuse = (message, usage = false) => {
|
|
24
|
+
console.error(`helix-icons: ${message}`);
|
|
25
|
+
if (usage) {
|
|
26
|
+
console.error(`\n${USAGE}`);
|
|
27
|
+
}
|
|
28
|
+
return 1;
|
|
29
|
+
};
|
|
21
30
|
export function main(argv) {
|
|
22
|
-
if (argv
|
|
31
|
+
if (argv.includes('--help') || argv.includes('-h')) {
|
|
23
32
|
console.log(USAGE);
|
|
24
|
-
return
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
if (argv[0] !== 'build') {
|
|
36
|
+
return refuse(argv[0] === undefined ? 'needs a command' : `${argv[0]} is not a command`, true);
|
|
25
37
|
}
|
|
26
38
|
const sources = [];
|
|
27
39
|
let list;
|
|
28
40
|
let out = 'icons.generated.ts';
|
|
29
41
|
let index = false;
|
|
30
42
|
let typeImport;
|
|
31
|
-
for (
|
|
43
|
+
for (let at = 1; at < argv.length; at += 1) {
|
|
44
|
+
const flag = argv[at];
|
|
45
|
+
if (flag === '--index') {
|
|
46
|
+
index = true;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const value = after(argv, at);
|
|
32
50
|
switch (flag) {
|
|
33
|
-
case '--source':
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
console.error('helix-icons: --source needs a directory');
|
|
37
|
-
return 1;
|
|
51
|
+
case '--source':
|
|
52
|
+
if (value === undefined) {
|
|
53
|
+
return refuse('--source needs a directory');
|
|
38
54
|
}
|
|
39
|
-
sources.push({ directory: resolve(
|
|
55
|
+
sources.push({ directory: resolve(value) });
|
|
40
56
|
break;
|
|
41
|
-
}
|
|
42
57
|
case '--suffix': {
|
|
43
|
-
const suffix = after(argv, at);
|
|
44
58
|
const last = sources.at(-1);
|
|
45
|
-
if (
|
|
46
|
-
|
|
47
|
-
return 1;
|
|
59
|
+
if (value === undefined || last === undefined) {
|
|
60
|
+
return refuse('--suffix names what a file carries, after the --source it is for');
|
|
48
61
|
}
|
|
49
|
-
last.suffix =
|
|
62
|
+
last.suffix = value;
|
|
50
63
|
break;
|
|
51
64
|
}
|
|
52
65
|
case '--list':
|
|
53
|
-
|
|
66
|
+
if (value === undefined) {
|
|
67
|
+
return refuse('--list needs a file');
|
|
68
|
+
}
|
|
69
|
+
list = value;
|
|
54
70
|
break;
|
|
55
71
|
case '--out':
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
72
|
+
if (value === undefined) {
|
|
73
|
+
return refuse('--out needs a file');
|
|
74
|
+
}
|
|
75
|
+
out = value;
|
|
60
76
|
break;
|
|
61
77
|
case '--type-import':
|
|
62
|
-
|
|
78
|
+
if (value === undefined) {
|
|
79
|
+
return refuse('--type-import needs the module to import the type from');
|
|
80
|
+
}
|
|
81
|
+
typeImport = value;
|
|
63
82
|
break;
|
|
64
83
|
default:
|
|
65
|
-
|
|
84
|
+
return refuse(`${flag} is not an option of build`, true);
|
|
66
85
|
}
|
|
86
|
+
at += 1;
|
|
67
87
|
}
|
|
68
88
|
if (sources.length === 0) {
|
|
69
89
|
console.error('helix-icons: needs at least one --source\n');
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fusion.dev/helix-icons",
|
|
3
3
|
"description": "Helix icon set.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.207.1",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ross Sheppard <ross.sheppard@fusion.dev>",
|
|
7
7
|
"repository": {
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"types": "./dist/build.d.ts",
|
|
26
26
|
"default": "./dist/build.js"
|
|
27
27
|
},
|
|
28
|
+
"./package.json": "./package.json",
|
|
28
29
|
"./regular": {
|
|
29
30
|
"types": "./dist/regular.d.ts",
|
|
30
31
|
"default": "./dist/regular.js"
|