@massimo-cassandro/create-favicons 1.1.0 → 1.3.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.
- package/index.mjs +19 -18
- package/package.json +4 -11
- package/readme.md +6 -2
- package/src/create-favicons.mjs +17 -181
- package/src/create-ico.OLD.mjs +32 -0
- package/src/create-ico.mjs +18 -0
- package/src/create-png.mjs +21 -0
- package/src/create-snippet.mjs +50 -0
- package/src/create-svg.mjs +15 -0
- package/src/create-webmanifest.mjs +14 -0
- package/src/{defaults.mjs → default-params.mjs} +5 -9
- package/src/init.mjs +1 -1
- package/src/parse-params.mjs +48 -0
- package/src/print-frame.mjs +1 -1
- package/src/print-result.mjs +61 -0
- /package/src/{init-start.txt → init-start-text.txt} +0 -0
package/index.mjs
CHANGED
|
@@ -9,12 +9,13 @@ import * as path from 'path';
|
|
|
9
9
|
|
|
10
10
|
import chalk from 'chalk';
|
|
11
11
|
|
|
12
|
+
import { parseParams } from './src/parse-params.mjs';
|
|
13
|
+
import { default_params } from './src/default-params.mjs';
|
|
12
14
|
import { createFavicons } from './src/create-favicons.mjs';
|
|
13
|
-
import { defaults } from './src/defaults.mjs';
|
|
14
15
|
import { init } from './src/init.mjs';
|
|
15
16
|
|
|
16
17
|
// nome del file di configurazione, se utilizzato
|
|
17
|
-
const
|
|
18
|
+
const config_filename = 'create-favicons-cfg.mjs';
|
|
18
19
|
|
|
19
20
|
try {
|
|
20
21
|
|
|
@@ -25,39 +26,39 @@ try {
|
|
|
25
26
|
|
|
26
27
|
} else {
|
|
27
28
|
|
|
28
|
-
let
|
|
29
|
+
let work_dir;
|
|
29
30
|
const dir_param_idx = process.argv.findIndex(el => /^--dir/.test(el) );
|
|
30
31
|
|
|
31
32
|
if(dir_param_idx !== -1) {
|
|
32
|
-
[,
|
|
33
|
+
[, work_dir] = process.argv[dir_param_idx].split('=');
|
|
33
34
|
|
|
34
35
|
} else {
|
|
35
|
-
|
|
36
|
+
work_dir = './';
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
|
|
39
|
+
work_dir = path.resolve(process.cwd(), work_dir) ;
|
|
39
40
|
|
|
40
|
-
import(path.resolve(params.work_dir, cfg_filename))
|
|
41
|
-
.then((custom_params) => {
|
|
42
41
|
|
|
43
|
-
|
|
42
|
+
if(fs.existsSync(path.resolve(work_dir, config_filename))) {
|
|
44
43
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
import(path.resolve(work_dir, config_filename))
|
|
45
|
+
.then((config_params) => {
|
|
46
|
+
|
|
47
|
+
const imported_params = [...(Array.isArray(config_params.default)? config_params.default : [config_params.default])];
|
|
48
|
+
|
|
49
|
+
imported_params.forEach(params_item => {
|
|
50
|
+
createFavicons(parseParams(params_item, work_dir));
|
|
51
|
+
});
|
|
48
52
|
|
|
49
|
-
} else {
|
|
50
|
-
createFavicons({ ...defaults, ...params, ...custom_params.default });
|
|
51
|
-
}
|
|
52
53
|
});
|
|
53
54
|
|
|
54
|
-
} else if(fs.existsSync(path.resolve(
|
|
55
|
+
} else if(default_params.src_img && fs.existsSync(path.resolve(work_dir, default_params.src_img))) {
|
|
55
56
|
|
|
56
|
-
createFavicons(
|
|
57
|
+
createFavicons(parseParams(null, work_dir));
|
|
57
58
|
|
|
58
59
|
} else {
|
|
59
60
|
|
|
60
|
-
throw `'${
|
|
61
|
+
throw new Error( `'${config_filename}' e '${defaults.src_img}' non presenti`);
|
|
61
62
|
}
|
|
62
63
|
|
|
63
64
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@massimo-cassandro/create-favicons",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Favicon files builder",
|
|
5
5
|
"bin": {
|
|
6
6
|
"create-favicons": "./index.mjs"
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
"publishConfig": {
|
|
15
15
|
"access": "public"
|
|
16
16
|
},
|
|
17
|
-
|
|
18
17
|
"author": "Massimo Cassandro",
|
|
19
18
|
"license": "MIT",
|
|
20
19
|
"repository": {
|
|
@@ -43,14 +42,8 @@
|
|
|
43
42
|
},
|
|
44
43
|
"dependencies": {
|
|
45
44
|
"chalk": "^5.3.0",
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"sharp": "^0.32.6",
|
|
50
|
-
"svgo": "^3.0.4",
|
|
51
|
-
"to-ico": "^1.1.5"
|
|
52
|
-
},
|
|
53
|
-
"devDependencies": {
|
|
54
|
-
"@massimo-cassandro/linters-config": "^1.6.1"
|
|
45
|
+
"sharp": "^0.33.2",
|
|
46
|
+
"sharp-ico": "^0.1.5",
|
|
47
|
+
"svgo": "^3.2.0"
|
|
55
48
|
}
|
|
56
49
|
}
|
package/readme.md
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Crea i file favicons come descritto in [How to Favicon in 2024](https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
I file da elaborare devono essere in formato SVG, mentre quelli generati sono in formato SVG (favicon), PNG (apple-touch-icon e altri file per android), e ICO (altro favicon per compatibilità con i browser meno recenti). Vengono inoltre genrati i file `manifest.webmanifest` e uno snippet html, opzionale, con i tag `link` per l'inserimento degli elementi generati.
|
|
6
|
+
|
|
7
|
+
Le immagini sono generate con [Sharp](https://sharp.pixelplumbing.com/), [SVGO](https://github.com/svg/svgo) e [sharp-ico](https://github.com/ssnangua/sharp-ico).
|
|
8
|
+
|
|
9
|
+
## Utilizzo
|
|
6
10
|
|
|
7
11
|
```bash
|
|
8
12
|
npx create-favicons [--dir=./path/to/dir]
|
|
@@ -32,7 +36,7 @@ const params = [{ /* ... */ }];
|
|
|
32
36
|
export default params;
|
|
33
37
|
```
|
|
34
38
|
|
|
35
|
-
`params` può essere un
|
|
39
|
+
`params` può essere un oggetto o un array. In quest'ultimo caso, ogni elemento dell'array corrisponde ad un diverso set di favicons.
|
|
36
40
|
|
|
37
41
|
Per creare un file di cfg di esempio **nella directory corrente** (con tutti i valori di default e la loro descrizione),
|
|
38
42
|
utilizzare il comando:
|
package/src/create-favicons.mjs
CHANGED
|
@@ -1,200 +1,36 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
2
|
|
|
3
|
-
import * as fs from 'fs';
|
|
4
|
-
import * as path from 'path';
|
|
3
|
+
// import * as fs from 'fs';
|
|
4
|
+
// import * as path from 'path';
|
|
5
5
|
import chalk from 'chalk';
|
|
6
6
|
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
import { printFrame } from './print-frame.mjs';
|
|
15
|
-
import { remove_homedir_string } from './remove-homedir-string.mjs';
|
|
7
|
+
import { createIco } from './create-ico.mjs';
|
|
8
|
+
import { createPng } from './create-png.mjs';
|
|
9
|
+
import { createSvg } from './create-svg.mjs';
|
|
10
|
+
import { createWebmanifest } from './create-webmanifest.mjs';
|
|
11
|
+
import { createSnippet } from './create-snippet.mjs';
|
|
12
|
+
import { printResult } from './print-result.mjs';
|
|
16
13
|
|
|
17
14
|
|
|
18
15
|
export function createFavicons(params) {
|
|
19
16
|
|
|
20
17
|
try {
|
|
21
18
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (!fs.existsSync(output_dir)){
|
|
25
|
-
fs.mkdirSync(output_dir);
|
|
26
|
-
}
|
|
27
|
-
|
|
19
|
+
console.error(chalk.green('Creating favicons...'));
|
|
28
20
|
|
|
29
|
-
// https://sharp.pixelplumbing.com/api-constructor
|
|
30
21
|
Promise.all([
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// .toFile(`${output_dir}/${size[0]}`)
|
|
40
|
-
.toBuffer()
|
|
41
|
-
.then(bufferData => {
|
|
42
|
-
|
|
43
|
-
// ottimizzazione PNG / JPG
|
|
44
|
-
// https://github.com/imagemin/imagemin
|
|
45
|
-
// https://github.com/imagemin/imagemin-pngquant
|
|
46
|
-
// https://github.com/imagemin/imagemin-jpegtran
|
|
47
|
-
// https://web.dev/use-imagemin-to-compress-images/
|
|
48
|
-
|
|
49
|
-
imagemin.buffer(bufferData, {
|
|
50
|
-
plugins: [
|
|
51
|
-
imageminJpegtran(),
|
|
52
|
-
imageminPngquant({
|
|
53
|
-
quality: params.imagemin_png_quality,
|
|
54
|
-
dithering: false,
|
|
55
|
-
strip: true,
|
|
56
|
-
verbose: true
|
|
57
|
-
})
|
|
58
|
-
]
|
|
59
|
-
}).then( result => {
|
|
60
|
-
fs.writeFileSync(`${output_dir}/${size[0]}`, result);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
})
|
|
64
|
-
.catch(err => { throw err; });
|
|
65
|
-
|
|
66
|
-
}));
|
|
67
|
-
|
|
68
|
-
// favicon.ico
|
|
69
|
-
// https://github.com/kevva/to-ico
|
|
70
|
-
// alternativa: https://github.com/steambap/png-to-ico
|
|
71
|
-
|
|
72
|
-
// const ico_source = fs.readFileSync(`${output_dir}/apple-touch-icon.png`);
|
|
73
|
-
|
|
74
|
-
sharp(path.resolve(params.work_dir, params.small_src_img?? params.src_img))
|
|
75
|
-
.png()
|
|
76
|
-
// .then(info => console.log(info))
|
|
77
|
-
.toBuffer()
|
|
78
|
-
.then(bufferData => {
|
|
79
|
-
|
|
80
|
-
toIco([bufferData], {
|
|
81
|
-
sizes: [16, 32],
|
|
82
|
-
resize: true
|
|
83
|
-
}).then( result => {
|
|
84
|
-
fs.writeFileSync(`${output_dir}/favicon.ico`, result);
|
|
85
|
-
});
|
|
22
|
+
createSvg(params),
|
|
23
|
+
createPng(params),
|
|
24
|
+
createIco(params),
|
|
25
|
+
createWebmanifest(params),
|
|
26
|
+
createSnippet(params),
|
|
27
|
+
])
|
|
28
|
+
.then(result => {
|
|
29
|
+
printResult(params);
|
|
86
30
|
|
|
87
31
|
})
|
|
88
|
-
.catch(err => { throw err; });
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
// favicon.svg (SVGO)
|
|
92
|
-
// TODO add extra config ???
|
|
93
|
-
const svgString = fs.readFileSync(path.resolve(params.work_dir, params.small_src_img?? params.src_img), 'utf8');
|
|
94
|
-
const svg_result = optimize(svgString, {
|
|
95
|
-
multipass: true,
|
|
96
|
-
});
|
|
97
|
-
fs.writeFileSync(`${output_dir}/favicon.svg`, svg_result.data, {force: true});
|
|
98
|
-
|
|
99
|
-
// web manifest
|
|
100
|
-
const manifest = {
|
|
101
|
-
icons: [192, 512].map( size => {
|
|
102
|
-
return { src: `./icon-${size}.png`, type: 'image/png', sizes: `${size}x${size}` };
|
|
103
|
-
}),
|
|
104
|
-
...(params.webmanifest_extra?? {})
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
fs.writeFileSync(`${output_dir}/manifest.webmanifest`, JSON.stringify(manifest, null, ' '));
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const snippet_path = params.snippet_path? path.resolve(params.work_dir, params.snippet_path) : output_dir;
|
|
111
|
-
|
|
112
|
-
// snippet
|
|
113
|
-
if(params.snippet_name || params.snippet_target_file) {
|
|
114
|
-
|
|
115
|
-
if (!params.snippet_target_file && !fs.existsSync(snippet_path)){
|
|
116
|
-
fs.mkdirSync(snippet_path);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
params.snippet_language = params.snippet_language.toLowerCase();
|
|
120
|
-
|
|
121
|
-
const cache_buster = params.add_cache_buster? `?_=${Date.now()}` : '',
|
|
122
|
-
create_href = nome_file => params.href_template.replace('%_file_name_%', nome_file)
|
|
123
|
-
.replace('%_cache_buster_%', cache_buster);
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
let snippet_content = `<link rel="icon" href="${create_href('favicon.ico')}" sizes="any">\n` +
|
|
127
|
-
`<link rel="icon" href="${create_href('favicon.svg')}" type="image/svg+xml">\n` +
|
|
128
|
-
`<link rel="apple-touch-icon" href="${create_href('apple-touch-icon.png')}">\n` +
|
|
129
|
-
`<link rel="manifest" href="${create_href('manifest.webmanifest')}">`;
|
|
130
|
-
|
|
131
|
-
if (params.snippet_language === 'pug') {
|
|
132
|
-
snippet_content = snippet_content.replace(/<link (.*?)>/g, 'link($1)');
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
snippet_content = params.snippet_template.replace('%_link_tags_%', snippet_content);
|
|
136
|
-
|
|
137
|
-
if (params.snippet_target_file) {
|
|
138
|
-
|
|
139
|
-
params.snippet_target_file = path.resolve(params.work_dir, params.snippet_target_file);
|
|
140
|
-
|
|
141
|
-
if (fs.existsSync(params.snippet_target_file)) {
|
|
142
|
-
const targetFileContent = fs.readFileSync(path.resolve(params.snippet_target_file), 'utf8'),
|
|
143
|
-
regexp = /<!-- ?favicon-snippet-start ?-->(.*?)<!-- ?favicon-snippet-end ?-->/mis;
|
|
144
|
-
|
|
145
|
-
fs.writeFileSync(params.snippet_target_file,
|
|
146
|
-
targetFileContent.replace(regexp,
|
|
147
|
-
`<!-- favicon-snippet-start -->\n${snippet_content}\n<!-- favicon-snippet-end -->`
|
|
148
|
-
)
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
} else {
|
|
152
|
-
throw `Il file '${params.snippet_target_file}' non esiste`;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
} else {
|
|
156
|
-
|
|
157
|
-
fs.writeFileSync(
|
|
158
|
-
`${snippet_path}/${params.snippet_name}`,
|
|
159
|
-
snippet_content
|
|
160
|
-
);
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// print result
|
|
166
|
-
let extra_strings = [];
|
|
167
|
-
|
|
168
|
-
if(snippet_path !== output_dir && params.snippet_name !== null) {
|
|
169
|
-
extra_strings = [
|
|
170
|
-
{string: ''},
|
|
171
|
-
{string: `Il file snippet '${params.snippet_name}' è stato salvato nella directory:`, color: 'green'},
|
|
172
|
-
{string: remove_homedir_string(snippet_path), color: 'yellow'},
|
|
173
|
-
];
|
|
174
|
-
|
|
175
|
-
} else if(params.snippet_name === null) {
|
|
176
|
-
extra_strings = [
|
|
177
|
-
{string: ''},
|
|
178
|
-
{string: 'Il file snippet non è stato generato', color: 'magentaBright'},
|
|
179
|
-
];
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
printFrame({
|
|
184
|
-
strings: [
|
|
185
|
-
{string: '** Creazione favicons completata **', color: 'bgGreen'},
|
|
186
|
-
{string: ''},
|
|
187
|
-
{string: 'I file generati sono nella directory:', color: 'green'},
|
|
188
|
-
{string: remove_homedir_string(output_dir), color: 'yellow'},
|
|
189
|
-
...extra_strings
|
|
190
|
-
],
|
|
191
|
-
frameColor: 'green',
|
|
192
|
-
frameType: 'single'
|
|
193
|
-
});
|
|
194
|
-
|
|
195
32
|
|
|
196
33
|
} catch(err) {
|
|
197
|
-
|
|
198
34
|
console.error(chalk.bgRed(` ${err} `));
|
|
199
35
|
}
|
|
200
36
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import sharp from 'sharp';
|
|
3
|
+
import toIco from 'to-ico';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
// https://github.com/kevva/to-ico
|
|
7
|
+
// alternativa: https://github.com/steambap/png-to-ico
|
|
8
|
+
|
|
9
|
+
// const ico_source = fs.readFileSync(`${output_dir}/apple-touch-icon.png`);
|
|
10
|
+
|
|
11
|
+
export async function createIco(params) {
|
|
12
|
+
|
|
13
|
+
await sharp(params.small_src_img?? params.src_img)
|
|
14
|
+
// .png()
|
|
15
|
+
// .then(info => console.log(info))
|
|
16
|
+
.toBuffer()
|
|
17
|
+
.then(bufferData => {
|
|
18
|
+
|
|
19
|
+
toIco([bufferData], {
|
|
20
|
+
sizes: [16, 32],
|
|
21
|
+
resize: true
|
|
22
|
+
}).then( async result => {
|
|
23
|
+
await fs.promises.writeFile(`${params.output_dir}/favicon.ico`, result, {
|
|
24
|
+
encoding: "utf8",
|
|
25
|
+
flag: "w",
|
|
26
|
+
mode: 0o666
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
})
|
|
31
|
+
.catch(err => { throw new Error( err + ' (createIco)'); });
|
|
32
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import sharp from 'sharp';
|
|
2
|
+
import ico from 'sharp-ico';
|
|
3
|
+
|
|
4
|
+
// https://github.com/ssnangua/sharp-ico
|
|
5
|
+
|
|
6
|
+
export async function createIco(params) {
|
|
7
|
+
|
|
8
|
+
ico.sharpsToIco(
|
|
9
|
+
[sharp(params.small_src_img?? params.src_img)],
|
|
10
|
+
`${params.output_dir}/favicon.ico`,
|
|
11
|
+
{
|
|
12
|
+
sizes: [16, 32],
|
|
13
|
+
// sizes: "default", // equal to [256, 128, 64, 48, 32, 24, 16]
|
|
14
|
+
resizeOptions: {}, // sharp resize optinos
|
|
15
|
+
}
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import sharp from 'sharp';
|
|
2
|
+
|
|
3
|
+
export async function createPng(params) {
|
|
4
|
+
|
|
5
|
+
// https://sharp.pixelplumbing.com/api-constructor
|
|
6
|
+
// https://sharp.pixelplumbing.com/api-output#png
|
|
7
|
+
Promise.all([
|
|
8
|
+
['apple-touch-icon.png', 180],
|
|
9
|
+
['icon-192.png', 192],
|
|
10
|
+
['icon-512.png', 512]
|
|
11
|
+
].map(file => {
|
|
12
|
+
sharp(params.src_img)
|
|
13
|
+
.resize({ width: file[1], fit: 'inside' })
|
|
14
|
+
.png(params.png_parameters)
|
|
15
|
+
.toFile(`${params.output_dir}/${file[0]}`)
|
|
16
|
+
|
|
17
|
+
}))
|
|
18
|
+
.catch(err => { throw new Error( err ); });
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
|
|
3
|
+
export async function createSnippet(params) {
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
if(params.create_snippet) {
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
const cache_buster = params.add_cache_buster? `?_=${Date.now()}` : '',
|
|
10
|
+
create_href = nome_file => params.href_template.replace('%_file_name_%', nome_file)
|
|
11
|
+
.replace('%_cache_buster_%', cache_buster);
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
let snippet_content = `<link rel="icon" href="${create_href('favicon.ico')}" sizes="any">\n` +
|
|
15
|
+
`<link rel="icon" href="${create_href('favicon.svg')}" type="image/svg+xml">\n` +
|
|
16
|
+
`<link rel="apple-touch-icon" href="${create_href('apple-touch-icon.png')}">\n` +
|
|
17
|
+
`<link rel="manifest" href="${create_href('manifest.webmanifest')}">`;
|
|
18
|
+
|
|
19
|
+
if (params.snippet_language === 'pug') {
|
|
20
|
+
snippet_content = snippet_content.replace(/<link (.*?)>/g, 'link($1)');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
snippet_content = params.snippet_template.replace('%_link_tags_%', snippet_content);
|
|
24
|
+
|
|
25
|
+
if (params.snippet_target_file) {
|
|
26
|
+
|
|
27
|
+
if (fs.existsSync(params.snippet_target_file)) {
|
|
28
|
+
const targetFileContent = fs.readFileSync(params.snippet_target_file, 'utf8'),
|
|
29
|
+
regexp = /<!-- ?favicon-snippet-start ?-->(.*?)<!-- ?favicon-snippet-end ?-->/mis;
|
|
30
|
+
|
|
31
|
+
fs.promises.writeFile(params.snippet_target_file,
|
|
32
|
+
targetFileContent.replace(regexp,
|
|
33
|
+
`<!-- favicon-snippet-start -->\n${snippet_content}\n<!-- favicon-snippet-end -->`
|
|
34
|
+
)
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
} else {
|
|
38
|
+
throw new Error( `Il file '${params.snippet_target_file}' non esiste` );
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
} else {
|
|
42
|
+
|
|
43
|
+
fs.promises.writeFile(
|
|
44
|
+
`${params.snippet_path}/${params.snippet_name}`,
|
|
45
|
+
snippet_content
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { optimize } from 'svgo';
|
|
2
|
+
import * as fs from 'fs/promises';
|
|
3
|
+
|
|
4
|
+
export async function createSvg(params) {
|
|
5
|
+
|
|
6
|
+
// TODO add extra config ???
|
|
7
|
+
fs.readFile(params.small_src_img?? params.src_img, { encoding: 'utf8' })
|
|
8
|
+
.then(svgString => {
|
|
9
|
+
|
|
10
|
+
const svg_result = optimize(svgString, { multipass: true});
|
|
11
|
+
|
|
12
|
+
fs.writeFile(`${params.output_dir}/favicon.svg`, svg_result.data);
|
|
13
|
+
|
|
14
|
+
});
|
|
15
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as fs from 'fs/promises';
|
|
2
|
+
|
|
3
|
+
export async function createWebmanifest(params) {
|
|
4
|
+
// web manifest
|
|
5
|
+
const manifest = {
|
|
6
|
+
icons: [192, 512].map( size => {
|
|
7
|
+
return { src: `./icon-${size}.png`, type: 'image/png', sizes: `${size}x${size}` };
|
|
8
|
+
}),
|
|
9
|
+
...(params.webmanifest_extra?? {})
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
fs.writeFile(`${params.output_dir}/manifest.webmanifest`, JSON.stringify(manifest, null, ' '));
|
|
13
|
+
|
|
14
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const
|
|
1
|
+
export const default_params = {
|
|
2
2
|
|
|
3
3
|
// delimitazione porzione da copiare nel file init
|
|
4
4
|
/*** INIT START ***/
|
|
@@ -73,16 +73,12 @@ export const defaults = {
|
|
|
73
73
|
// problemi di caching del browser
|
|
74
74
|
add_cache_buster: false,
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
// IMAGEMIN PARAMETERS
|
|
78
76
|
//****************************************************************************
|
|
77
|
+
|
|
78
|
+
// SHARP PNG PARAMETERS
|
|
79
79
|
// parametri per i file PNG
|
|
80
|
-
// vedi https://
|
|
81
|
-
|
|
82
|
-
// exceed the max quality. If conversion results in quality below the min quality
|
|
83
|
-
// the image won't be saved.
|
|
84
|
-
// Min and max are numbers in range 0 (worst) to 1 (perfect), similar to JPEG.
|
|
85
|
-
imagemin_png_quality: [0.3, 0.6]
|
|
80
|
+
// vedi https://sharp.pixelplumbing.com/api-output#png
|
|
81
|
+
png_parameters: {compressionLevel: 5, quality: 60, palette: true}
|
|
86
82
|
|
|
87
83
|
|
|
88
84
|
/*** INIT END ***/
|
package/src/init.mjs
CHANGED
|
@@ -22,7 +22,7 @@ export function init() {
|
|
|
22
22
|
|
|
23
23
|
const start_string = '/*** INIT START ***/',
|
|
24
24
|
end_string = '/*** INIT END ***/',
|
|
25
|
-
init_start_text = fs.readFileSync(src_dir +'./init-start.txt', 'utf8');
|
|
25
|
+
init_start_text = fs.readFileSync(src_dir +'./init-start-text.txt', 'utf8');
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { default_params } from './default-params.mjs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
|
|
5
|
+
export function parseParams(config_params = null, work_dir = process.cwd()) {
|
|
6
|
+
|
|
7
|
+
try {
|
|
8
|
+
|
|
9
|
+
const params = {...default_params, ...(config_params??{})}
|
|
10
|
+
params.work_dir = work_dir;
|
|
11
|
+
|
|
12
|
+
[
|
|
13
|
+
'src_img',
|
|
14
|
+
'small_src_img',
|
|
15
|
+
'snippet_path',
|
|
16
|
+
'snippet_target_file',
|
|
17
|
+
'output_dir'
|
|
18
|
+
].forEach(item =>
|
|
19
|
+
params[item] = params[item]? path.resolve(params.work_dir, params[item]) : null
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
// creazione dir output se non esiste
|
|
23
|
+
if (!fs.existsSync(params.output_dir)){
|
|
24
|
+
fs.mkdirSync(params.output_dir);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// definizione snippet_path e creazione dir se necessario
|
|
28
|
+
params.create_snippet = params.snippet_name || params.snippet_target_file;
|
|
29
|
+
|
|
30
|
+
if(params.create_snippet) {
|
|
31
|
+
|
|
32
|
+
params.snippet_path = params.snippet_path?? params.output_dir;
|
|
33
|
+
|
|
34
|
+
if (!params.snippet_target_file && !fs.existsSync(params.snippet_path )){
|
|
35
|
+
fs.mkdirSync(params.snippet_path );
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
params.snippet_language = params.snippet_language.toLowerCase();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
return params;
|
|
43
|
+
|
|
44
|
+
} catch(e) {
|
|
45
|
+
console.error( e ); // eslint-disable-line
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
}
|
package/src/print-frame.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
|
|
4
|
+
// https://github.com/chalk/chalk
|
|
4
5
|
export function printFrame(options) {
|
|
5
6
|
|
|
6
7
|
/*
|
|
@@ -27,7 +28,6 @@ export function printFrame(options) {
|
|
|
27
28
|
|
|
28
29
|
options.strings = options.strings.map(item => {return {...string_defaults, ...item }; });
|
|
29
30
|
|
|
30
|
-
// TODO bold underline ecc...
|
|
31
31
|
// aggiunta spazi sulle righe `bg`
|
|
32
32
|
options.strings.forEach(item => {
|
|
33
33
|
if(/^bg/.test(item.color)) {
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { printFrame } from './print-frame.mjs';
|
|
2
|
+
import { remove_homedir_string } from './remove-homedir-string.mjs';
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
// https://github.com/chalk/chalk
|
|
7
|
+
export function printResult(params) {
|
|
8
|
+
|
|
9
|
+
function printSize(size) {
|
|
10
|
+
if(size > 1024) {
|
|
11
|
+
return `${(size / 1024).toFixed(2)} KB`;
|
|
12
|
+
} else {
|
|
13
|
+
return `${size} B`;
|
|
14
|
+
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// print result
|
|
19
|
+
let extra_strings = [];
|
|
20
|
+
|
|
21
|
+
// immagini generate e dimensioni
|
|
22
|
+
[
|
|
23
|
+
'apple-touch-icon.png',
|
|
24
|
+
'favicon.ico',
|
|
25
|
+
'favicon.svg',
|
|
26
|
+
'icon-192.png',
|
|
27
|
+
'icon-512.png',
|
|
28
|
+
'manifest.webmanifest'
|
|
29
|
+
].forEach(item => {
|
|
30
|
+
const stats = fs.statSync(`${params.output_dir}/${item}`);
|
|
31
|
+
extra_strings.push({string: `${item}: ${printSize(stats.size)}`, color: 'greenBright'});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
if(params.snippet_path !== params.output_dir && params.snippet_name !== null) {
|
|
35
|
+
extra_strings.push(
|
|
36
|
+
{string: ''},
|
|
37
|
+
{string: `Il file snippet '${params.snippet_name}' è stato salvato nella directory:`, color: 'green'},
|
|
38
|
+
{string: remove_homedir_string(params.snippet_path ), color: 'yellow'},
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
} else if(params.snippet_name === null) {
|
|
42
|
+
extra_strings.push(
|
|
43
|
+
{string: ''},
|
|
44
|
+
{string: 'Il file snippet non è stato generato', color: 'magentaBright'},
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
printFrame({
|
|
50
|
+
strings: [
|
|
51
|
+
{string: '** Creazione favicons completata **', color: 'bgGreen'},
|
|
52
|
+
{string: ''},
|
|
53
|
+
{string: 'I file generati sono nella directory:', color: 'green'},
|
|
54
|
+
{string: remove_homedir_string(params.output_dir), color: 'yellow'},
|
|
55
|
+
{string: ''},
|
|
56
|
+
...extra_strings
|
|
57
|
+
],
|
|
58
|
+
frameColor: 'green',
|
|
59
|
+
frameType: 'single'
|
|
60
|
+
});
|
|
61
|
+
}
|
|
File without changes
|