better-asset 0.1.1 → 0.1.2
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 +21 -14
- package/assets.config.schema.json +20 -12
- package/package.json +1 -1
- package/src/config.js +25 -6
- package/src/generate.js +22 -3
package/README.md
CHANGED
|
@@ -94,15 +94,15 @@ Add a `$schema` key for editor autocompletion:
|
|
|
94
94
|
|
|
95
95
|
### Asset Fields
|
|
96
96
|
|
|
97
|
-
| Field | Type
|
|
98
|
-
| ------------- |
|
|
99
|
-
| `name` | string
|
|
100
|
-
| `source` | string
|
|
101
|
-
| `sizes` | array
|
|
102
|
-
| `destination` | string
|
|
103
|
-
| `format` | string
|
|
104
|
-
| `sizeInName` | boolean
|
|
105
|
-
| `ico` | object
|
|
97
|
+
| Field | Type | Required | Default | Description |
|
|
98
|
+
| ------------- | ----------------- | -------- | ------- | -------------------------------------------- |
|
|
99
|
+
| `name` | string | yes | — | Base name for generated files |
|
|
100
|
+
| `source` | string | yes | — | Source filename (relative to `source_dir`) |
|
|
101
|
+
| `sizes` | array | yes | — | Sizes to generate |
|
|
102
|
+
| `destination` | string | yes | — | Output directory (relative to project root) |
|
|
103
|
+
| `format` | string | no | `"png"` | Output format: `png`, `webp`, `jpeg`, `avif` |
|
|
104
|
+
| `sizeInName` | boolean | no | auto | Force include/exclude size in filename |
|
|
105
|
+
| `ico` | boolean \| object | no | — | Generate a `favicon.ico` |
|
|
106
106
|
|
|
107
107
|
## Size Rules
|
|
108
108
|
|
|
@@ -134,7 +134,14 @@ Override per asset:
|
|
|
134
134
|
|
|
135
135
|
## ICO Generation
|
|
136
136
|
|
|
137
|
-
|
|
137
|
+
Use `ico` as either a boolean shortcut or an object:
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{ "ico": true }
|
|
141
|
+
{ "ico": false }
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Or use the object form for more control:
|
|
138
145
|
|
|
139
146
|
```json
|
|
140
147
|
{
|
|
@@ -145,10 +152,10 @@ Add an `ico` object to generate a real `favicon.ico`:
|
|
|
145
152
|
}
|
|
146
153
|
```
|
|
147
154
|
|
|
148
|
-
| Field | Type | Default | Description |
|
|
149
|
-
| ---------- | ------- | ------- | -------------------------------------- |
|
|
150
|
-
| `required` | boolean | — | Whether to generate the `.ico` file |
|
|
151
|
-
| `size` | number | `64` | Size of the embedded PNG in the `.ico` |
|
|
155
|
+
| Field | Type | Required | Default | Description |
|
|
156
|
+
| ---------- | ------- | -------- | ------- | -------------------------------------- |
|
|
157
|
+
| `required` | boolean | yes | — | Whether to generate the `.ico` file |
|
|
158
|
+
| `size` | number | no | `64` | Size of the embedded PNG in the `.ico` |
|
|
152
159
|
|
|
153
160
|
## License
|
|
154
161
|
|
|
@@ -62,21 +62,29 @@
|
|
|
62
62
|
"description": "Force include/exclude size in filename. Default: included when multiple sizes, omitted for single size."
|
|
63
63
|
},
|
|
64
64
|
"ico": {
|
|
65
|
-
"
|
|
66
|
-
|
|
67
|
-
"required": ["required"],
|
|
68
|
-
"properties": {
|
|
69
|
-
"required": {
|
|
65
|
+
"oneOf": [
|
|
66
|
+
{
|
|
70
67
|
"type": "boolean",
|
|
71
|
-
"description": "
|
|
68
|
+
"description": "Shortcut: true generates favicon.ico (default size: 64), false disables it."
|
|
72
69
|
},
|
|
73
|
-
|
|
74
|
-
"type": "
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
70
|
+
{
|
|
71
|
+
"type": "object",
|
|
72
|
+
"description": "Generate a favicon.ico file from this asset.",
|
|
73
|
+
"required": ["required"],
|
|
74
|
+
"properties": {
|
|
75
|
+
"required": {
|
|
76
|
+
"type": "boolean",
|
|
77
|
+
"description": "Whether to generate the .ico file."
|
|
78
|
+
},
|
|
79
|
+
"size": {
|
|
80
|
+
"type": "integer",
|
|
81
|
+
"minimum": 1,
|
|
82
|
+
"default": 64,
|
|
83
|
+
"description": "Size of the embedded PNG in the .ico file (default: 64)."
|
|
84
|
+
}
|
|
85
|
+
}
|
|
78
86
|
}
|
|
79
|
-
|
|
87
|
+
]
|
|
80
88
|
}
|
|
81
89
|
}
|
|
82
90
|
}
|
package/package.json
CHANGED
package/src/config.js
CHANGED
|
@@ -50,6 +50,29 @@ export async function loadConfig(configPath) {
|
|
|
50
50
|
if (!Array.isArray(asset.sizes) || asset.sizes.length === 0) {
|
|
51
51
|
throw new Error(`Asset "${asset.name}" must have a non-empty "sizes" array.`);
|
|
52
52
|
}
|
|
53
|
+
|
|
54
|
+
if (asset.ico !== undefined) {
|
|
55
|
+
const isBooleanIco = typeof asset.ico === "boolean";
|
|
56
|
+
const isObjectIco = typeof asset.ico === "object" && asset.ico !== null && !Array.isArray(asset.ico);
|
|
57
|
+
|
|
58
|
+
if (!isBooleanIco && !isObjectIco) {
|
|
59
|
+
throw new Error(`Asset "${asset.name}" has invalid "ico". Use boolean or object.`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (isObjectIco && asset.ico.size !== undefined) {
|
|
63
|
+
if (!Number.isInteger(asset.ico.size) || asset.ico.size < 1) {
|
|
64
|
+
throw new Error(`Asset "${asset.name}" has invalid "ico.size". Use a positive integer.`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (isObjectIco && asset.ico.required === undefined) {
|
|
69
|
+
throw new Error(`Asset "${asset.name}" must include "ico.required" when "ico" is an object.`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (isObjectIco && typeof asset.ico.required !== "boolean") {
|
|
73
|
+
throw new Error(`Asset "${asset.name}" has invalid "ico.required". Use true or false.`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
53
76
|
}
|
|
54
77
|
|
|
55
78
|
return config;
|
|
@@ -74,17 +97,13 @@ export function defaultConfig() {
|
|
|
74
97
|
source: "favicon.svg",
|
|
75
98
|
sizes: [16, 32, 48],
|
|
76
99
|
destination: "public/icons",
|
|
77
|
-
ico:
|
|
78
|
-
required: true,
|
|
79
|
-
size: 96,
|
|
80
|
-
},
|
|
100
|
+
ico: true,
|
|
81
101
|
},
|
|
82
102
|
{
|
|
83
103
|
name: "opengraph-image",
|
|
84
104
|
source: "icon.svg",
|
|
85
105
|
sizes: ["1200x630"],
|
|
86
|
-
destination: "public
|
|
87
|
-
format: "jpeg",
|
|
106
|
+
destination: "public",
|
|
88
107
|
},
|
|
89
108
|
],
|
|
90
109
|
};
|
package/src/generate.js
CHANGED
|
@@ -5,6 +5,24 @@ import { parseSize, buildFileName, generateImage, generateIco } from "./image.js
|
|
|
5
5
|
import { cleanGeneratedFiles } from "./clean.js";
|
|
6
6
|
import * as log from "./log.js";
|
|
7
7
|
|
|
8
|
+
function resolveIcoConfig(ico) {
|
|
9
|
+
if (ico === true) {
|
|
10
|
+
return { enabled: true, size: 64 };
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (ico === false || ico == null) {
|
|
14
|
+
return { enabled: false, size: 64 };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (typeof ico === "object") {
|
|
18
|
+
const enabled = ico.required === true;
|
|
19
|
+
const size = typeof ico.size === "number" ? ico.size : 64;
|
|
20
|
+
return { enabled, size };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return { enabled: false, size: 64 };
|
|
24
|
+
}
|
|
25
|
+
|
|
8
26
|
export async function generate(cwd, configFlag) {
|
|
9
27
|
const configPath = resolveConfigPath(cwd, configFlag);
|
|
10
28
|
|
|
@@ -43,11 +61,12 @@ export async function generate(cwd, configFlag) {
|
|
|
43
61
|
totalFiles++;
|
|
44
62
|
}
|
|
45
63
|
|
|
46
|
-
|
|
64
|
+
const ico = resolveIcoConfig(asset.ico);
|
|
65
|
+
if (ico.enabled) {
|
|
47
66
|
const icoPath = path.join(destinationDir, "favicon.ico");
|
|
48
|
-
await generateIco(sourcePath, icoPath,
|
|
67
|
+
await generateIco(sourcePath, icoPath, ico.size);
|
|
49
68
|
|
|
50
|
-
log.success("favicon.ico", `${
|
|
69
|
+
log.success("favicon.ico", `${ico.size}×${ico.size}`);
|
|
51
70
|
totalFiles++;
|
|
52
71
|
}
|
|
53
72
|
}
|