@massimo-cassandro/create-favicons 1.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.
- package/index.mjs +69 -0
- package/package.json +56 -0
- package/readme.md +86 -0
- package/src/create-favicons.mjs +201 -0
- package/src/defaults.mjs +90 -0
- package/src/init-start.txt +16 -0
- package/src/init.mjs +51 -0
- package/src/print-frame.mjs +51 -0
- package/src/remove-homedir-string.mjs +9 -0
package/index.mjs
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/* eslint-disable no-console */
|
|
4
|
+
/* eslint-env node */
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
|
|
10
|
+
import chalk from 'chalk';
|
|
11
|
+
|
|
12
|
+
import { createFavicons } from './src/create-favicons.mjs';
|
|
13
|
+
import { defaults } from './src/defaults.mjs';
|
|
14
|
+
import { init } from './src/init.mjs';
|
|
15
|
+
|
|
16
|
+
// nome del file di configurazione, se utilizzato
|
|
17
|
+
const cfg_filename = 'create-favicons-cfg.mjs';
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
|
|
21
|
+
// init: creazione file cfg base
|
|
22
|
+
if(process.argv.indexOf('init') !== -1) {
|
|
23
|
+
|
|
24
|
+
init();
|
|
25
|
+
|
|
26
|
+
} else {
|
|
27
|
+
|
|
28
|
+
let params = {};
|
|
29
|
+
const dir_param_idx = process.argv.findIndex(el => /^--dir/.test(el) );
|
|
30
|
+
|
|
31
|
+
if(dir_param_idx !== -1) {
|
|
32
|
+
[, params.work_dir] = process.argv[dir_param_idx].split('=');
|
|
33
|
+
|
|
34
|
+
} else {
|
|
35
|
+
params.work_dir = './';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if(fs.existsSync(path.resolve(params.work_dir, cfg_filename))) {
|
|
39
|
+
|
|
40
|
+
import(path.resolve(params.work_dir, cfg_filename))
|
|
41
|
+
.then((custom_params) => {
|
|
42
|
+
|
|
43
|
+
if(Array.isArray(custom_params.default)) {
|
|
44
|
+
|
|
45
|
+
custom_params.default.forEach(item => {
|
|
46
|
+
createFavicons({ ...defaults, ...params, ...item });
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
} else {
|
|
50
|
+
createFavicons({ ...defaults, ...params, ...custom_params.default });
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
} else if(fs.existsSync(path.resolve(params.work_dir, defaults.src_img))) {
|
|
55
|
+
|
|
56
|
+
createFavicons({...defaults, ...params});
|
|
57
|
+
|
|
58
|
+
} else {
|
|
59
|
+
|
|
60
|
+
throw `'${cfg_filename}' e '${defaults.src_img}' non presenti`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
} catch(err) {
|
|
68
|
+
console.error(chalk.bgRed(`\n ${err} \n`));
|
|
69
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@massimo-cassandro/create-favicons",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Favicon files builder",
|
|
5
|
+
"bin": {
|
|
6
|
+
"create-favicons": "./index.mjs"
|
|
7
|
+
},
|
|
8
|
+
"type": "module",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"update-version": "node ./src/update-version/index.mjs",
|
|
11
|
+
"upd@m": "node ./src/upd@m/index.mjs",
|
|
12
|
+
"npm-publish": "npm publish"
|
|
13
|
+
},
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
"author": "Massimo Cassandro",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/massimo-cassandro/create-favicons.git#main"
|
|
23
|
+
},
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/massimo-cassandro/create-favicons/issues"
|
|
26
|
+
},
|
|
27
|
+
"homepage": "https://github.com/massimo-cassandro/create-favicons/tree/main#readme",
|
|
28
|
+
"eslintConfig": {
|
|
29
|
+
"extends": [
|
|
30
|
+
"./node_modules/@massimo-cassandro/linters-config/eslintrc.js"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"stylelint": {
|
|
34
|
+
"extends": "@massimo-cassandro/linters-config/stylelintrc.js"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"src/**/*",
|
|
38
|
+
"index.mjs"
|
|
39
|
+
],
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">= 18.0.0",
|
|
42
|
+
"npm": ">= 9.0.0"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"chalk": "^5.3.0",
|
|
46
|
+
"imagemin": "^8.0.1",
|
|
47
|
+
"imagemin-jpegtran": "^7.0.0",
|
|
48
|
+
"imagemin-pngquant": "^9.0.2",
|
|
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"
|
|
55
|
+
}
|
|
56
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Create favicons
|
|
2
|
+
|
|
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
|
+
|
|
5
|
+
Utilizzo:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx create-favicons [--dir=./path/to/dir]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Lo script agisce normalmente nella directory corrente, ma, utilizzando il parametro opzionale `--dir`,
|
|
12
|
+
è possibile specificare una directory alternativa (percorso relativo alla dir di esecuzione).
|
|
13
|
+
|
|
14
|
+
Lo script in prima battuta cerca nella dir di lavoro il file `create-favicons-cfg.mjs` che contiene un oggetto
|
|
15
|
+
con tutti i parametri necessari (vedi di seguito).
|
|
16
|
+
|
|
17
|
+
In sua assenza, cerca il file `favicon-src.svg` da utilizzare come sorgente per tutte le immagini, e assumendo i valori di default (vedi dopo) per tutti gli altri parametri.
|
|
18
|
+
|
|
19
|
+
Tra gli altri, è possibile spcificare il parametro `small_src_img` nel caso sia necessario specificare un'immagine ottimizzata per le piccole dimensioni (32px).
|
|
20
|
+
|
|
21
|
+
Il formato migliore per i file sorgenti è SVG, o in alternativa PNG.
|
|
22
|
+
|
|
23
|
+
In assenza di entrambi i file viene restituito un errore.
|
|
24
|
+
|
|
25
|
+
I parametri di default sono elencati in dettaglio nel file `src/create-favicons/src/defaults.mjs`,
|
|
26
|
+
e possono essere personalizzati nel file di configurazione, che deve avere questa forma:
|
|
27
|
+
|
|
28
|
+
```javascript
|
|
29
|
+
// file create-favicons-cfg.mjs
|
|
30
|
+
const params = [{ /* ... */ }];
|
|
31
|
+
|
|
32
|
+
export default params;
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`params` può essere un ogetto o un array. In quest'ultimo caso, ogni elemento dell'array corrisponde ad un diverso set di favicons.
|
|
36
|
+
|
|
37
|
+
Per creare un file di cfg di esempio **nella directory corrente** (con tutti i valori di default e la loro descrizione),
|
|
38
|
+
utilizzare il comando:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npx create-favicons init
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Utilizzo da remoto
|
|
45
|
+
|
|
46
|
+
I comandi possono essere eseguiti anche senza installare preventivamente il package:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
npx --package=@massimo-cassandro/dev-utilities create-favicons init
|
|
50
|
+
npx --package=@massimo-cassandro/dev-utilities create-favicons [--dir=...]
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Esecuzione
|
|
55
|
+
|
|
56
|
+
Lo script produce le varie immagini png ed svg, il file `manifest.webmanifest` e uno snippet html (o nel linguaggio indicato nel parametro `snippet_language`).
|
|
57
|
+
Tutte le immagini vengono ottimizzate con [SVGO](https://github.com/svg/svgo) e [imagemin](https://github.com/imagemin/imagemin).
|
|
58
|
+
|
|
59
|
+
Tutti file vengono salvati nella dir indicata in `output_dir` (default: directory corrente).
|
|
60
|
+
|
|
61
|
+
Opzionalmente il file snippet può essere salvato in una directory differente (`snippet_path`) o si può decidere di non crearlo,
|
|
62
|
+
impostando il valore `snippet_name` a `null`.
|
|
63
|
+
|
|
64
|
+
Nel file di configurazione è anche possibile impostare il parametro `webmanifest_extra`, che permette di aggiungere voci aggiuntive al file *manifest*.
|
|
65
|
+
Per ulteriori info: <https://developer.mozilla.org/en-US/docs/Web/Manifest>
|
|
66
|
+
|
|
67
|
+
File generati:
|
|
68
|
+
|
|
69
|
+
```html
|
|
70
|
+
<link rel="icon" href="/favicon.ico" sizes="any"> <!-- 32×32 + 16x16 -->
|
|
71
|
+
<link rel="icon" href="/icon.svg" type="image/svg+xml">
|
|
72
|
+
<link rel="apple-touch-icon" href="/apple-touch-icon.png"> <!-- 180×180 -->
|
|
73
|
+
<link rel="manifest" href="/manifest.webmanifest">
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
```javascript
|
|
77
|
+
// manifest.webmanifest
|
|
78
|
+
{
|
|
79
|
+
"icons": [
|
|
80
|
+
{ "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" },
|
|
81
|
+
{ "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" }
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Vedi anche esempio in <https://github.com/massimo-cassandro/dev-utilities/tree/main/test/test/create-favicons-test>.
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
|
|
7
|
+
import sharp from 'sharp';
|
|
8
|
+
import toIco from 'to-ico';
|
|
9
|
+
import { optimize } from 'svgo';
|
|
10
|
+
import imagemin from 'imagemin';
|
|
11
|
+
import imageminJpegtran from 'imagemin-jpegtran';
|
|
12
|
+
import imageminPngquant from 'imagemin-pngquant';
|
|
13
|
+
|
|
14
|
+
import { printFrame } from './print-frame.mjs';
|
|
15
|
+
import { remove_homedir_string } from './remove-homedir-string.mjs';
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
export function createFavicons(params) {
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
|
|
22
|
+
const output_dir = path.resolve(params.work_dir, params.output_dir);
|
|
23
|
+
|
|
24
|
+
if (!fs.existsSync(output_dir)){
|
|
25
|
+
fs.mkdirSync(output_dir);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
// https://sharp.pixelplumbing.com/api-constructor
|
|
30
|
+
Promise.all([
|
|
31
|
+
['apple-touch-icon.png', 180],
|
|
32
|
+
['icon-192.png', 192],
|
|
33
|
+
['icon-512.png', 512]
|
|
34
|
+
].map(size => {
|
|
35
|
+
sharp(path.resolve(params.work_dir, params.src_img))
|
|
36
|
+
.resize({ width: size[1], fit: 'inside' })
|
|
37
|
+
.png()
|
|
38
|
+
// .then(info => console.log(info))
|
|
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
|
+
});
|
|
86
|
+
|
|
87
|
+
})
|
|
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
|
+
|
|
196
|
+
} catch(err) {
|
|
197
|
+
|
|
198
|
+
console.error(chalk.bgRed(` ${err} `));
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
}
|
package/src/defaults.mjs
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
export const defaults = {
|
|
2
|
+
|
|
3
|
+
// delimitazione porzione da copiare nel file init
|
|
4
|
+
/*** INIT START ***/
|
|
5
|
+
|
|
6
|
+
// tutti i percorsi sono relativi alla dir di lavoro
|
|
7
|
+
|
|
8
|
+
// immagine sorgente SVG o PNG 512x512
|
|
9
|
+
src_img: 'favicon-src.svg',
|
|
10
|
+
|
|
11
|
+
// sorgente opzionale per immagini piccole (32px)
|
|
12
|
+
small_src_img: null,
|
|
13
|
+
|
|
14
|
+
// directory output (percorso relativo alla dir di lavoro)
|
|
15
|
+
// se la dir non esiste, viene creata
|
|
16
|
+
output_dir: 'favicons-output',
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
// WEBMANIFEST
|
|
20
|
+
//****************************************************************************
|
|
21
|
+
// chiavi aggiuntive per webmanifest, normalmente non necessarie per il browser
|
|
22
|
+
// vedi https://developer.mozilla.org/en-US/docs/Web/Manifest
|
|
23
|
+
// esempio:
|
|
24
|
+
// webmanifest_extra: {
|
|
25
|
+
// name: "my Application",
|
|
26
|
+
// short_name: "my app",
|
|
27
|
+
// background_color: "#ffffff",
|
|
28
|
+
// theme_color: "#ffffff",
|
|
29
|
+
// display: "fullscreen"
|
|
30
|
+
// }
|
|
31
|
+
webmanifest_extra: null,
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
// SNIPPET
|
|
35
|
+
//****************************************************************************
|
|
36
|
+
|
|
37
|
+
// nome del file snippet, compresa l'estensione
|
|
38
|
+
// se questo parametro è null e anche `snippet_target_file` lo è, lo snippet non viene generato
|
|
39
|
+
snippet_name: 'favicon.html',
|
|
40
|
+
|
|
41
|
+
// path (relativo a questo file) in cui salvare lo snippet
|
|
42
|
+
// se null, viene utilizzato lo stesso percorso indicato in `output_dir`
|
|
43
|
+
// se la dir non esiste, viene creata
|
|
44
|
+
snippet_path: null,
|
|
45
|
+
|
|
46
|
+
// path del file in cui scrivere le righe dello snippet
|
|
47
|
+
// questa impostazione è alternativa alle due precedenti e, se presente, queste
|
|
48
|
+
// ultime vengono ignorate.
|
|
49
|
+
// Per utilizzarla, le va assegnato il percorso del file (già esistente) nel quale
|
|
50
|
+
// scrivere le righe delle snippet.
|
|
51
|
+
// Il file deve contenere dei segnaposti per contrassegnare lo spazio entro il quale
|
|
52
|
+
// scrivere lo snippets
|
|
53
|
+
// <!-- favicon-snippet-start --><!-- favicon-snippet-end -->
|
|
54
|
+
snippet_target_file: null,
|
|
55
|
+
|
|
56
|
+
// linguaggio da utilizzare per la sintassi dello snippet html
|
|
57
|
+
// html o pug
|
|
58
|
+
snippet_language: 'html',
|
|
59
|
+
|
|
60
|
+
// template per la costruzione dello snippet.
|
|
61
|
+
// si tratta di una stringa (anche su più righe) in cui deve essere presente
|
|
62
|
+
// '%_link_tags_%', che verrà sostituito con i tag links dei vari file
|
|
63
|
+
snippet_template: '%_link_tags_%',
|
|
64
|
+
|
|
65
|
+
// template per la costruzione di ogni singolo attributo `href` dei tag link.
|
|
66
|
+
// deve contenere la stringa '%_file_name_%', che conterrà il nome del file,
|
|
67
|
+
// e la stringa '%_cache_buster_%' (se attivata)', che conterrà `?_=xxxx`, dove
|
|
68
|
+
// 'xxxx' rappresenta il timestamp generato per annullare la cache.
|
|
69
|
+
// Va scritto tenendo conto del linguaggio utilizzato.
|
|
70
|
+
href_template: '/%_file_name_%%_cache_buster_%',
|
|
71
|
+
|
|
72
|
+
// se true aggiunge allo snippet una query string per ovviare ad eventuali
|
|
73
|
+
// problemi di caching del browser
|
|
74
|
+
add_cache_buster: false,
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
// IMAGEMIN PARAMETERS
|
|
78
|
+
//****************************************************************************
|
|
79
|
+
// parametri per i file PNG
|
|
80
|
+
// vedi https://www.npmjs.com/package/imagemin-pngquant
|
|
81
|
+
// Instructs pngquant to use the least amount of colors required to meet or
|
|
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]
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
/*** INIT END ***/
|
|
89
|
+
|
|
90
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/*
|
|
2
|
+
File di configurazione per `create-favicons`.
|
|
3
|
+
|
|
4
|
+
I valori indicati sono quelli di default.
|
|
5
|
+
Per avviare la generazione delle favicon digitare
|
|
6
|
+
|
|
7
|
+
npx create-favicons
|
|
8
|
+
|
|
9
|
+
dalla directory che contiene questo file.
|
|
10
|
+
|
|
11
|
+
Creazione favicons (senza installare il package nel progetto):
|
|
12
|
+
npx --package=@massimo-cassandro/create-favicons create-favicons (dalla dir corrente)
|
|
13
|
+
|
|
14
|
+
Altre info: https://github.com/massimo-cassandro/create-favicons
|
|
15
|
+
|
|
16
|
+
*/
|
package/src/init.mjs
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/* eslint-env node */
|
|
2
|
+
|
|
3
|
+
import { URL } from 'url';
|
|
4
|
+
import * as fs from 'fs';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import { printFrame } from './print-frame.mjs';
|
|
8
|
+
import { remove_homedir_string } from './remove-homedir-string.mjs';
|
|
9
|
+
|
|
10
|
+
export function init() {
|
|
11
|
+
// const __filename = new URL('', import.meta.url).pathname;
|
|
12
|
+
// Will contain trailing slash
|
|
13
|
+
const src_dir = new URL('.', import.meta.url).pathname,
|
|
14
|
+
cfg_sample_file = process.cwd() + '/create-favicons-cfg.mjs';
|
|
15
|
+
|
|
16
|
+
if(fs.existsSync(cfg_sample_file)) {
|
|
17
|
+
throw `${cfg_sample_file} già presente`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
let default_params = fs.readFileSync(src_dir + './defaults.mjs', 'UTF8');
|
|
22
|
+
|
|
23
|
+
const start_string = '/*** INIT START ***/',
|
|
24
|
+
end_string = '/*** INIT END ***/',
|
|
25
|
+
init_start_text = fs.readFileSync(src_dir +'./init-start.txt', 'utf8');
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
default_params = default_params.substring(
|
|
30
|
+
default_params.indexOf(start_string) + start_string.length, //from
|
|
31
|
+
default_params.indexOf(end_string)
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
fs.writeFileSync(
|
|
35
|
+
cfg_sample_file,
|
|
36
|
+
init_start_text.trim() + '\n\n' +
|
|
37
|
+
'const params = [{\n' +
|
|
38
|
+
default_params +
|
|
39
|
+
'\n}];\n\n' +
|
|
40
|
+
'export default params;'
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
printFrame({
|
|
44
|
+
strings: [
|
|
45
|
+
{string: 'File di configurazione di generato:', color: 'green'},
|
|
46
|
+
{string: remove_homedir_string(cfg_sample_file), color: 'bgGreen'},
|
|
47
|
+
],
|
|
48
|
+
frameColor: 'green',
|
|
49
|
+
frameType: 'double'
|
|
50
|
+
});
|
|
51
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
|
|
4
|
+
export function printFrame(options) {
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
stringsArray = [
|
|
8
|
+
{string: '__string__', color: 'green', bg: false, bold: false, underline: false},
|
|
9
|
+
{...}
|
|
10
|
+
]
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const defaults = {
|
|
14
|
+
strings: [],
|
|
15
|
+
frameColor: 'green',
|
|
16
|
+
frametype: 'single'
|
|
17
|
+
},
|
|
18
|
+
string_defaults = { string: '', color: 'green', bg: false, bold: false, underline: false},
|
|
19
|
+
frame_lines = {
|
|
20
|
+
single: ['┌', '┐', '└', '┘', '┈', '│'],
|
|
21
|
+
double: ['╔', '╗', '╚', '╝', '═', '║']
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
options = {...defaults, ...options};
|
|
25
|
+
|
|
26
|
+
const frames_elements = frame_lines[options.frametype];
|
|
27
|
+
|
|
28
|
+
options.strings = options.strings.map(item => {return {...string_defaults, ...item }; });
|
|
29
|
+
|
|
30
|
+
// TODO bold underline ecc...
|
|
31
|
+
// aggiunta spazi sulle righe `bg`
|
|
32
|
+
options.strings.forEach(item => {
|
|
33
|
+
if(/^bg/.test(item.color)) {
|
|
34
|
+
item.string = ` ${item.string} `;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const total_length = Math.max( ...(options.strings.map(item => item.string.length)) ) + 2;
|
|
39
|
+
|
|
40
|
+
console.log( chalk[options.frameColor]( `\n${frames_elements[0]}` + frames_elements[4].repeat(total_length) + frames_elements[1]) );
|
|
41
|
+
|
|
42
|
+
options.strings.forEach(item => {
|
|
43
|
+
console.log(
|
|
44
|
+
chalk[options.frameColor](`${frames_elements[5]} `) +
|
|
45
|
+
chalk[item.color](item.string) + ' '.repeat(total_length - item.string.length - 2) +
|
|
46
|
+
chalk[options.frameColor](` ${frames_elements[5]}`)
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
console.log( chalk[options.frameColor]( frames_elements[2] + frames_elements[4].repeat(total_length) + `${frames_elements[3]}\n` ) );
|
|
51
|
+
}
|